data-primals-engine 1.1.7-rc1 → 1.1.8-rc.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.
@@ -52,6 +52,8 @@ export const websiteTranslations = {
52
52
  "modelcreator.hiddenable.hint": "Une option sera disponible pour afficher cette donnée ou la masquer (il sera masqué par défaut).",
53
53
 
54
54
  "tourpoint.importDatapack": "Importez des packs de données pré-construits avec notre galerie de packs : Sites internets, e-commerce, CRM, et plus encore !",
55
+ "tourpoint.tutorials": "Laisse-vous guider en suivant nos tutoriels pas à pas !",
56
+
55
57
  "add_language": "Ajouter...",
56
58
  "select_or_add_language": "Sélectionnez ou ajoutez une langue pour commencer.",
57
59
  "field.richtext_t": "Texte enrichi traduit",
@@ -521,8 +523,8 @@ export const websiteTranslations = {
521
523
  "prez1.5": "Support des traductions et langues",
522
524
  "links.deploy_api": "Déployez votre API",
523
525
  "links.documentation": "Documentation",
524
- "links.demo": "Essayez maintenant !",
525
- "filterstringfield.placeholder.regex": 'Expression régulière',
526
+ "links.demo": "Démarrer la démo",
527
+ "filterstringfield.placeholder.regex": 'Expression régulière'
526
528
 
527
529
  }
528
530
  },
@@ -594,6 +596,8 @@ export const websiteTranslations = {
594
596
  "api.data.serverStorageFull": "The server has reached its maximum storage capacity. Please try again later.",
595
597
 
596
598
  "tourpoint.importDatapack": "Import pre-built data packs with our pack gallery: Websites, e-commerce, CRM, and more!",
599
+ "tourpoint.tutorials": "Let yourself be guided by following our step-by-step tutorials!",
600
+
597
601
  "add_language": "Add...",
598
602
  "select_or_add_language": "Select or add a language to get started.",
599
603
  "field.richtext_t": "Translated rich text",
@@ -1479,7 +1483,7 @@ export const websiteTranslations = {
1479
1483
  "dataimporter.title": "Import data into {{model}}",
1480
1484
  "dataimporter.hasCsvHeaders": "Does the CSV file contain a header row?",
1481
1485
  "dataimporter.info": "Import your JSON or CSV file containing the required data for your model. Your data will be copied to your personal database. The transfer rate is {{constante}}",
1482
- "links.demo": "Try the demo!",
1486
+ "links.demo": "Start the demo",
1483
1487
  "filterstringfield.placeholder.regex": 'Regular expression',
1484
1488
  "cgu.h1": "Terms of Use (TOU)",
1485
1489
  "cgu.h1.1": "1. Introduction",
@@ -1925,8 +1929,8 @@ export const websiteTranslations = {
1925
1929
  // channel
1926
1930
  field_channel_name: 'Name',
1927
1931
  field_channel_description: 'Description',
1928
- field_channel_type: 'Type',
1929
- },
1932
+ field_channel_type: 'Type'
1933
+ }
1930
1934
  },
1931
1935
  es: {
1932
1936
  translation: {
@@ -1996,6 +2000,8 @@ export const websiteTranslations = {
1996
2000
  "api.data.serverStorageFull": "El servidor ha alcanzado su capacidad máxima de almacenamiento. Inténtelo de nuevo más tarde.",
1997
2001
 
1998
2002
  "tourpoint.importDatapack": "Importa paquetes de datos prediseñados con nuestra galería de paquetes: sitios web, comercio electrónico, CRM y más",
2003
+ "tourpoint.tutorials": "¡Déjate guiar por nuestros tutoriales paso a paso!",
2004
+
1999
2005
  "add_language": "Añadir...",
2000
2006
  "select_or_add_language": "Seleccione o añada un idioma para empezar.",
2001
2007
  "field.richtext_t": "Texto enriquecido traducido",
@@ -2881,7 +2887,7 @@ export const websiteTranslations = {
2881
2887
  "dataimporter.title": "Importar datos a {{model}}",
2882
2888
  "dataimporter.hasCsvHeaders": "¿El archivo CSV contiene una fila de encabezado?",
2883
2889
  "dataimporter.info": "Importa tu archivo JSON o CSV con los datos necesarios para tu modelo. Tus datos se copiarán a tu base de datos personal. La velocidad de transferencia es {{constante}}",
2884
- "links.demo": "¡Prueba la demo!",
2890
+ "links.demo": "Iniciar la demostración",
2885
2891
  "filterstringfield.placeholder.regex": 'Expresión regular',
2886
2892
  "cgu.h1": "Condiciones Generales de Uso (CGU)",
2887
2893
  "cgu.h1.1": "1. Introducción",
@@ -3332,8 +3338,8 @@ export const websiteTranslations = {
3332
3338
  // channel
3333
3339
  field_channel_name: 'Nombre',
3334
3340
  field_channel_description: 'Descripción',
3335
- field_channel_type: 'Tipo',
3336
- },
3341
+ field_channel_type: 'Tipo'
3342
+ }
3337
3343
  },
3338
3344
  pt: {
3339
3345
  translation: {
@@ -3403,6 +3409,7 @@ export const websiteTranslations = {
3403
3409
  "api.data.serverStorageFull": "O servidor atingiu a sua capacidade máxima de armazenamento. Tente novamente mais tarde.",
3404
3410
 
3405
3411
  "tourpoint.importDatapack": "Importe pacotes de dados pré-criados com a nossa galeria de pacotes: sites, comércio eletrónico, CRM e muito mais!",
3412
+ "tourpoint.tutorials": "Deixe-se guiar seguindo os nossos tutoriais passo a passo!",
3406
3413
  "add_language": "Adicionar...",
3407
3414
  "select_or_add_language": "Selecione ou adicione um idioma para começar.",
3408
3415
  "field.richtext_t": "Texto rico traduzido",
@@ -4291,7 +4298,7 @@ export const websiteTranslations = {
4291
4298
  "dataimporter.title": "Importar dados para {{model}}",
4292
4299
  "dataimporter.hasCsvHeaders": "O ficheiro CSV contém uma linha de cabeçalho?",
4293
4300
  "dataimporter.info": "Importe o seu ficheiro JSON ou CSV contendo os dados necessários para o seu modelo. Os seus dados serão copiados para a sua base de dados pessoal. A taxa de transferência é {{constante}}",
4294
- "links.demo": "Experimente a demonstração!",
4301
+ "links.demo": "Iniciar a demonstração",
4295
4302
  "filterstringfield.placeholder.regex": 'Expressão regular',
4296
4303
  "cgu.h1": "Termos e Condições Gerais de Uso (TCGU)",
4297
4304
  "cgu.h1.1": "1. Introdução",
@@ -4736,8 +4743,8 @@ export const websiteTranslations = {
4736
4743
  // channel
4737
4744
  field_channel_name: 'Nome',
4738
4745
  field_channel_description: 'Descrição',
4739
- field_channel_type: 'Tipo',
4740
- },
4746
+ field_channel_type: 'Tipo'
4747
+ }
4741
4748
  },
4742
4749
  de: {
4743
4750
  translation: {
@@ -4795,6 +4802,8 @@ export const websiteTranslations = {
4795
4802
  "api.data.serverStorageFull": "Der Server hat seine maximale Speicherkapazität erreicht. Bitte versuchen Sie es später erneut.",
4796
4803
 
4797
4804
  "tourpoint.importDatapack": "Vorgefertigte Datenpakete mit unserer Packgalerie importieren: Websites, E-Commerce, CRM und mehr!",
4805
+ "tourpoint.tutorials": "Lassen Sie sich von unseren Schritt-für-Schritt-Tutorials leiten!",
4806
+
4798
4807
  "add_language": "Hinzufügen...",
4799
4808
  "select_or_add_language": "Wählen oder fügen Sie eine Sprache hinzu, um zu beginnen.",
4800
4809
  "field.richtext_t": "Übersetzter Rich Text",
@@ -5672,7 +5681,7 @@ export const websiteTranslations = {
5672
5681
  "dataimporter.title": "Daten in {{model}} importieren",
5673
5682
  "dataimporter.hasCsvHeaders": "Enthält die CSV-Datei eine Kopfzeile?",
5674
5683
  "dataimporter.info": "Importieren Sie Ihre JSON- oder CSV-Datei mit den benötigten Daten für Ihr Modell. Ihre Daten werden in Ihre persönliche Datenbank kopiert. Die Übertragungsrate beträgt {{constante}}",
5675
- "links.demo": "Probieren Sie die Demo aus!",
5684
+ "links.demo": "Demo starten",
5676
5685
  "filterstringfield.placeholder.regex": 'Regulärer Ausdruck',
5677
5686
  "cgu.h1": "Nutzungsbedingungen (TOU)",
5678
5687
  "cgu.h1.1": "1. Einleitung",
@@ -6122,8 +6131,8 @@ export const websiteTranslations = {
6122
6131
  // channel
6123
6132
  field_channel_name: 'Name',
6124
6133
  field_channel_description: 'Beschreibung',
6125
- field_channel_type: 'Typ',
6126
- },
6134
+ field_channel_type: 'Typ'
6135
+ }
6127
6136
  },
6128
6137
  it: {
6129
6138
  translation: {
@@ -6193,6 +6202,7 @@ export const websiteTranslations = {
6193
6202
  "api.data.serverStorageFull": "Il server ha raggiunto la capacità massima di archiviazione. Riprova più tardi.",
6194
6203
 
6195
6204
  "tourpoint.importDatapack": "Importa pacchetti di dati predefiniti con la nostra galleria di pacchetti: siti web, e-commerce, CRM e altro ancora!",
6205
+ "tourpoint.tutorials": "Lasciati guidare seguendo i nostri tutorial passo dopo passo!",
6196
6206
  "add_language": "Aggiungi...",
6197
6207
  "select_or_add_language": "Seleziona o aggiungi una lingua per iniziare.",
6198
6208
  "field.richtext_t": "Rich text tradotto",
@@ -7077,7 +7087,7 @@ export const websiteTranslations = {
7077
7087
  "dataimporter.title": "Importa dati in {{model}}",
7078
7088
  "dataimporter.hasCsvHeaders": "Il file CSV contiene una riga di intestazione?",
7079
7089
  "dataimporter.info": "Importa il tuo file JSON o CSV contenente i dati necessari per il tuo modello. I tuoi dati verranno copiati nel tuo database personale. La velocità di trasferimento è {{constante}}",
7080
- "links.demo": "Prova la demo!",
7090
+ "links.demo": "Avvia la demo",
7081
7091
  "filterstringfield.placeholder.regex": 'Espressione regolare',
7082
7092
  "cgu.h1": "Termini di Utilizzo (TOU)",
7083
7093
  "cgu.h1.1": "1. Introduzione",
@@ -7522,8 +7532,8 @@ export const websiteTranslations = {
7522
7532
  // channel
7523
7533
  field_channel_name: 'Nome',
7524
7534
  field_channel_description: 'Descrizione',
7525
- field_channel_type: 'Tipo',
7526
- },
7535
+ field_channel_type: 'Tipo'
7536
+ }
7527
7537
  },
7528
7538
  cs: {
7529
7539
  translation: {
@@ -7593,6 +7603,7 @@ export const websiteTranslations = {
7593
7603
  "api.data.serverStorageFull": "Server dosáhl maximální úložné kapacity. Zkuste to prosím znovu později.",
7594
7604
 
7595
7605
  "tourpoint.importDatapack": "Importujte předpřipravené datové balíčky s naší galerií balíčků: Webové stránky, e-commerce, CRM a další!",
7606
+ "tourpoint.tutorials": "Nechte se vést našimi podrobnými tutoriály!",
7596
7607
  "add_language": "Přidat...",
7597
7608
  "select_or_add_language": "Vyberte nebo přidejte jazyk pro zahájení.",
7598
7609
  "field.richtext_t": "Přeložený formátovaný text",
@@ -8472,7 +8483,7 @@ export const websiteTranslations = {
8472
8483
  "dataimporter.title": "Importovat data do {{model}}",
8473
8484
  "dataimporter.hasCsvHeaders": "Obsahuje soubor CSV řádek záhlaví?",
8474
8485
  "dataimporter.info": "Importujte soubor JSON nebo CSV obsahující požadovaná data pro váš model. Vaše data budou zkopírována do vaší osobní databáze. Přenosová rychlost je {{constante}}",
8475
- "links.demo": "Vyzkoušejte demo!",
8486
+ "links.demo": "Spustit demo",
8476
8487
  "filterstringfield.placeholder.regex": 'Regulární výraz',
8477
8488
  "cgu.h1": "Podmínky použití (TOU)",
8478
8489
  "cgu.h1.1": "1. Úvod",
@@ -8917,8 +8928,8 @@ export const websiteTranslations = {
8917
8928
  // channel
8918
8929
  field_channel_name: 'Jméno',
8919
8930
  field_channel_description: 'Popis',
8920
- field_channel_type: 'Typ',
8921
- },
8931
+ field_channel_type: 'Typ'
8932
+ }
8922
8933
  },
8923
8934
  ru: {
8924
8935
  translation: {
@@ -8988,6 +8999,7 @@ export const websiteTranslations = {
8988
8999
  "api.data.serverStorageFull": "Сервер достиг максимального объёма хранилища. Повторите попытку позже.",
8989
9000
 
8990
9001
  "tourpoint.importDatapack": "Импортируйте готовые пакеты данных с помощью нашей галереи пакетов: веб-сайты, электронная коммерция, CRM и многое другое!",
9002
+ "tourpoint.tutorials": "Доверьтесь нашим пошаговым инструкциям!",
8991
9003
  "add_language": "Добавить...",
8992
9004
  "select_or_add_language": "Выберите или добавьте язык для начала работы",
8993
9005
  "field.richtext_t": "Переведенный форматированный текст",
@@ -9875,7 +9887,7 @@ export const websiteTranslations = {
9875
9887
  "dataimporter.title": "Импортировать данные в {{model}}",
9876
9888
  "dataimporter.hasCsvHeaders": "Содержит ли CSV-файл строку заголовка?",
9877
9889
  "dataimporter.info": "Импортируйте файл JSON или CSV, содержащий необходимые данные для вашей модели. Ваши данные будут скопированы в вашу личную базу данных. Скорость передачи составляет {{constante}}",
9878
- "links.demo": "Попробуйте демо!",
9890
+ "links.demo": "Запустить демо",
9879
9891
  "filterstringfield.placeholder.regex": 'Регулярное выражение',
9880
9892
  "cgu.h1": "Условия использования (TOU)",
9881
9893
  "cgu.h1.1": "1. Введение",
@@ -10322,8 +10334,8 @@ export const websiteTranslations = {
10322
10334
  // channel
10323
10335
  field_channel_name: 'Имя',
10324
10336
  field_channel_description: 'Описание',
10325
- field_channel_type: 'Тип',
10326
- },
10337
+ field_channel_type: 'Тип'
10338
+ }
10327
10339
  },
10328
10340
  ar: {
10329
10341
  translation: {
@@ -10395,6 +10407,8 @@ export const websiteTranslations = {
10395
10407
  "api.data.storageLimitExceeded": "سيتم تجاوز حد التخزين البالغ {{limit}} ميجابايت بهذه الإضافة.",
10396
10408
  "api.data.serverStorageFull": "وصل الخادم إلى الحد الأقصى لسعة التخزين. يُرجى المحاولة مرة أخرى لاحقًا.",
10397
10409
  "tourpoint.importDatapack": "استورد حزم البيانات المعدة مسبقًا باستخدام معرض الحزم لدينا: مواقع الويب، والتجارة الإلكترونية، وإدارة علاقات العملاء، والمزيد!",
10410
+ "tourpoint.tutorials": "دع نفسك تسترشد باتباع دروسنا التعليمية خطوة بخطوة!",
10411
+
10398
10412
  "add_language": "إضافة...",
10399
10413
  "select_or_add_language": "اختر أو أضف لغة للبدء.",
10400
10414
  "field.richtext_t": "نص منسق مترجم",
@@ -11297,7 +11311,7 @@ export const websiteTranslations = {
11297
11311
  "dataimporter.title": "استيراد البيانات إلى {{model}}",
11298
11312
  "dataimporter.hasCsvHeaders": "هل يحتوي ملف CSV على صف رأس؟",
11299
11313
  "dataimporter.info": "استورد ملف JSON أو CSV الذي يحتوي على البيانات المطلوبة لنموذجك. سيتم نسخ بياناتك إلى قاعدة بياناتك الشخصية. معدل النقل ثابت ({{constante}}).",
11300
- "links.demo": "جرب النسخة التجريبية!",
11314
+ "links.demo": "ابدأ العرض التوضيحي",
11301
11315
  "filterstringfield.placeholder.regex": 'تعبير عادي',
11302
11316
  "cgu.h1": "الشروط العامة للاستخدام (GTU)",
11303
11317
  "cgu.h1.1": "1. المقدمة",
@@ -11743,7 +11757,7 @@ export const websiteTranslations = {
11743
11757
  // channel
11744
11758
  field_channel_name: 'الاسم',
11745
11759
  field_channel_description: 'الوصف',
11746
- field_channel_type: 'النوع',
11760
+ field_channel_type: 'النوع'
11747
11761
  }
11748
11762
  },
11749
11763
  sv: {
@@ -11814,6 +11828,7 @@ export const websiteTranslations = {
11814
11828
  "api.data.serverStorageFull": "Servern har nått sin maximala lagringskapacitet. Försök igen senare.",
11815
11829
 
11816
11830
  "tourpoint.importDatapack": "Importera färdiga datapaket med vårt paketgalleri: Webbplatser, e-handel, CRM och mer!",
11831
+ "tourpoint.tutorials": "Låt dig vägledas av våra steg-för-steg-handledningar!",
11817
11832
  "add_language": "Lägg till...",
11818
11833
  "select_or_add_language": "Välj eller lägg till ett språk för att komma igång.",
11819
11834
  "field.richtext_t": "Översatt RTF",
@@ -12696,7 +12711,7 @@ export const websiteTranslations = {
12696
12711
  "dataimporter.title": "Importera data till {{model}}",
12697
12712
  "dataimporter.hasCsvHeaders": "Innehåller CSV-filen en rubrikrad?",
12698
12713
  "dataimporter.info": "Importera din JSON- eller CSV-fil som innehåller den data som krävs för din modell. Dina data kommer att kopieras till din personliga databas. Överföringshastigheten är {{constante}}",
12699
- "links.demo": "Testa demon!",
12714
+ "links.demo": "Starta demon",
12700
12715
  "filterstringfield.placeholder.regex": 'Reguljärt uttryck',
12701
12716
  "cgu.h1": "Användarvillkor (Användarvillkor)",
12702
12717
  "cgu.h1.1": "1. Introduktion",
@@ -13138,7 +13153,7 @@ export const websiteTranslations = {
13138
13153
  // channel
13139
13154
  field_channel_name: 'Namn',
13140
13155
  field_channel_description: 'Beskrivning',
13141
- field_channel_type: 'Typ',
13156
+ field_channel_type: 'Typ'
13142
13157
  }
13143
13158
  },
13144
13159
  el: {
@@ -13209,6 +13224,7 @@ export const websiteTranslations = {
13209
13224
  "api.data.serverStorageFull": "Ο διακομιστής έχει φτάσει στη μέγιστη χωρητικότητα αποθήκευσης. Παρακαλώ προσπαθήστε ξανά αργότερα.",
13210
13225
 
13211
13226
  "tourpoint.importDatapack": "Εισαγάγετε προκατασκευασμένα πακέτα δεδομένων με τη συλλογή πακέτων μας: Ιστότοποι, ηλεκτρονικό εμπόριο, CRM και πολλά άλλα!",
13227
+ "tourpoint.tutorials": "Ακολουθώντας τα βήμα προς βήμα εκπαιδευτικά μας βίντεο, αφήστε τον εαυτό σας να σας καθοδηγήσει!",
13212
13228
  "add_language": "Προσθήκη...",
13213
13229
  "select_or_add_language": "Επιλέξτε ή προσθέστε μια γλώσσα για να ξεκινήσετε.",
13214
13230
  "field.richtext_t": "Μεταφρασμένο εμπλουτισμένο κείμενο",
@@ -14096,7 +14112,7 @@ export const websiteTranslations = {
14096
14112
  "dataimporter.title": "Εισαγωγή δεδομένων στο {{model}}",
14097
14113
  "dataimporter.hasCsvHeaders": "Περιέχει το αρχείο CSV μια γραμμή κεφαλίδας;",
14098
14114
  "dataimporter.info": "Εισαγάγετε το αρχείο JSON που περιέχει τα απαιτούμενα δεδομένα για το μοντέλο σας. Τα δεδομένα σας θα αντιγραφούν στην προσωπική σας βάση δεδομένων. Ο ρυθμός μεταφοράς είναι {{constante}}",
14099
- "links.demo": "Δοκιμάστε την επίδειξη!",
14115
+ "links.demo": "Έναρξη της επίδειξης",
14100
14116
  "filterstringfield.placeholder.regex": "Κανονική έκφραση",
14101
14117
  "cgu.h1": "Γενικοί όροι χρήσης (GTU)",
14102
14118
  "cgu.h1.1": "1. Εισαγωγή",
@@ -14545,6 +14561,7 @@ export const websiteTranslations = {
14545
14561
  },
14546
14562
  fa: {
14547
14563
  "translation": {
14564
+ "links.demo": "شروع نسخهٔ نمایشی",
14548
14565
  "cb.searchOperator": "جستجوی یک عملگر...",
14549
14566
  "cb.changeOperator": "تغییر عملگر",
14550
14567
  "cb.deleteBlock": "حذف این بلوک",
@@ -14611,6 +14628,7 @@ export const websiteTranslations = {
14611
14628
  "api.data.serverStorageFull": "سرور به حداکثر ظرفیت ذخیره‌سازی خود رسیده است. لطفاً بعداً دوباره امتحان کنید.",
14612
14629
 
14613
14630
  "tourpoint.importDatapack": "بسته‌های داده از پیش ساخته شده را با گالری بسته‌های ما وارد کنید: وب‌سایت‌ها، تجارت الکترونیک، CRM و موارد دیگر!",
14631
+ "tourpoint.tutorials": "با دنبال کردن آموزش‌های گام به گام ما، خودتان را راهنمایی کنید!",
14614
14632
  "add_language": "اضافه کردن...",
14615
14633
  "select_or_add_language": "برای شروع، یک زبان را انتخاب یا اضافه کنید.",
14616
14634
  "field.richtext_t": "متن غنی ترجمه شده",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "data-primals-engine",
3
- "version": "1.1.7-rc1",
3
+ "version": "1.1.8-rc.1",
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",
@@ -102,13 +102,12 @@
102
102
  "client"
103
103
  ],
104
104
  "keywords": [
105
- "mongodb",
106
- "data",
107
- "primals",
105
+ "data-driven engine",
106
+ "headless CMS",
107
+ "backend",
108
108
  "automation",
109
- "aws",
110
- "bucket",
111
- "S3"
109
+ "AWS S3",
110
+ "MongoDB"
112
111
  ],
113
112
  "author": "anonympins",
114
113
  "license": "MIT",
package/src/engine.js CHANGED
@@ -41,17 +41,35 @@ const secureContext = tls.createSecureContext({
41
41
  ca: caFile, cert: certFile, key: keyFile
42
42
  });
43
43
 
44
+ export const dbUrl = process.env.CI ? 'mongodb://mongodb:27017' : (process.env.MONGO_DB_URL || 'mongodb://127.0.0.1:27017');
45
+
44
46
  const isTlsActive = !(!process.env.TLS || ["0", "false"].includes(process.env.TLS.toLowerCase()));
45
47
 
46
- // Connection URL
47
- export const dbUrl = process.env.CI ? 'mongodb://mongodb:27017' : (process.env.MONGO_DB_URL || 'mongodb://127.0.0.1:27017');
48
- export const MongoClient = new InternalMongoClient(dbUrl, {
49
- maxPoolSize: databasePoolSize,
50
- tls: isTlsActive,
51
- secureContext,
52
- tlsAllowInvalidCertificates,
53
- tlsAllowInvalidHostnames
54
- });
48
+ const clientOptions = {
49
+ maxPoolSize: databasePoolSize
50
+ };
51
+ // On ajoute les options TLS si elles sont activées
52
+ if (isTlsActive) {
53
+ clientOptions.tls = true;
54
+ // Chemin vers le certificat de l'autorité de certification (pour faire confiance au serveur)
55
+ if (process.env.CA_CERT) {
56
+ clientOptions.tlsCAFile = process.env.CA_CERT;
57
+ }
58
+ // Chemin vers le certificat et la clé du CLIENT (pour que le serveur vous fasse confiance)
59
+ if (process.env.CERT_KEY) {
60
+ clientOptions.tlsCertificateKeyFile = process.env.CERT_KEY;
61
+ }
62
+ // Options pour le développement (à utiliser avec prudence)
63
+ if (tlsAllowInvalidCertificates) {
64
+ clientOptions.tlsAllowInvalidCertificates = true;
65
+ }
66
+ if (tlsAllowInvalidHostnames) {
67
+ clientOptions.tlsAllowInvalidHostnames = true;
68
+ }
69
+ }
70
+
71
+ export const MongoClient = new InternalMongoClient(dbUrl, clientOptions);
72
+
55
73
 
56
74
  // Database Name
57
75
  export const MongoDatabase = MongoClient.db(dbName);
@@ -112,7 +112,7 @@ function sanitize(target, options = {}) {
112
112
  export function middleware(options = {}) {
113
113
  const hasOnSanitize = typeof options.onSanitize === 'function';
114
114
  return function (req, res, next) {
115
- ['body', 'params', 'headers', 'query'].forEach(function (key) {
115
+ ['body', 'fields', 'params', 'headers', 'query'].forEach(function (key) {
116
116
  if (req[key]) {
117
117
  // The _sanitize function mutates the req[key] object in-place.
118
118
  // We only need to capture whether it was sanitized to call the hook.
@@ -89,6 +89,8 @@ import {getAllPacks} from "../packs.js";
89
89
  import {throttleMiddleware} from "../middlewares/throttle.js";
90
90
  import {Config} from "../config.js";
91
91
  import {profiles} from "../../client/src/constants.js";
92
+ import {processFilterPlaceholders} from "../../client/src/filter.js";
93
+ import {tutorialsConfig} from "../../client/src/tutorials.js";
92
94
 
93
95
  // Obtenir le chemin du répertoire courant de manière fiable avec ES Modules
94
96
  const __filename = fileURLToPath(import.meta.url);
@@ -1507,6 +1509,128 @@ export async function onInit(defaultEngine) {
1507
1509
  }
1508
1510
  });
1509
1511
 
1512
+ /**
1513
+ * Route pour vérifier si une condition de complétion est remplie.
1514
+ * Utilise la fonction `searchData` existante pour interroger les données.
1515
+ */
1516
+ engine.post('/api/tutorials/check-completion', middlewareAuthenticator, async (req, res) => {
1517
+ try {
1518
+ const { model, filter, limit } = req.fields;
1519
+ const user = req.me;
1520
+
1521
+ if (!model || !filter || limit === undefined) {
1522
+ return res.status(400).json({ error: 'Payload de condition de complétion invalide.' });
1523
+ }
1524
+
1525
+ const processedFilter = processFilterPlaceholders(filter, user);
1526
+
1527
+ // On utilise la fonction de recherche interne de l'application
1528
+ const searchResult = await searchData({
1529
+ query: {
1530
+ model,
1531
+ filter: processedFilter,
1532
+ limit, // Optimisation : pas besoin de plus de résultats
1533
+ page: 1
1534
+ },
1535
+ user: user
1536
+ });
1537
+
1538
+ // searchData devrait renvoyer un `count` total des documents correspondants
1539
+ const isCompleted = searchResult.count >= limit;
1540
+
1541
+ res.json({ isCompleted });
1542
+
1543
+ } catch (error) {
1544
+ console.error('[Tutoriel Check Error]', error);
1545
+ res.status(500).json({ error: 'Erreur lors de la vérification de la complétion.', details: error.message });
1546
+ }
1547
+ });
1548
+
1549
+
1550
+
1551
+ engine.post('/api/tutorials/set-active', middlewareAuthenticator, async (req, res) => {
1552
+ try {
1553
+ const { tutorialState } = req.fields;
1554
+ const user = req.me;
1555
+
1556
+ if (tutorialState !== null && (typeof tutorialState !== 'object' || !tutorialState.id)) {
1557
+ return res.status(400).json({ error: 'Invalid tutorial state payload.' });
1558
+ }
1559
+
1560
+ // Créer une représentation de l'utilisateur mis à jour pour la réponse
1561
+ const updatedData = { activeTutorial: tutorialState };
1562
+
1563
+ await engine.userProvider.updateUser(user, updatedData);
1564
+
1565
+ // --- MODIFICATION ---
1566
+ res.json({
1567
+ success: true,
1568
+ updatedData // Renvoyer l'objet utilisateur complet
1569
+ });
1570
+
1571
+ } catch (error) {
1572
+ console.error('[Tutoriel Set Active Error]', error);
1573
+ res.status(500).json({ error: 'Error setting active tutorial.', details: error.message });
1574
+ }
1575
+ });
1576
+
1577
+ // ...
1578
+
1579
+ engine.post('/api/tutorials/:tutorialId/claim-rewards', middlewareAuthenticator, async (req, res) => {
1580
+ try {
1581
+ const { tutorialId } = req.params;
1582
+ const user = req.me; // L'objet utilisateur est déjà chargé
1583
+ const tutorial = tutorialsConfig.find(t => t.id === tutorialId);
1584
+
1585
+ if (!tutorial) return res.status(404).json({ error: 'Tutoriel non trouvé.' });
1586
+ if (!tutorial.rewards) return res.status(400).json({ error: 'Ce tutoriel n\'a pas de récompenses.' });
1587
+ if (user.completedTutorials?.includes(tutorialId)) {
1588
+ return res.status(400).json({ error: 'Tutoriel déjà terminé.' });
1589
+ }
1590
+
1591
+ const { xpBonus, skill, achievement, notification } = tutorial.rewards;
1592
+
1593
+ // --- LOGIQUE CORRIGÉE ---
1594
+ let newData= {};
1595
+ newData.xp = newData.xp || 0;
1596
+ newData.achievements = newData.achievements || [];
1597
+ newData.skills = newData.skills || [];
1598
+ newData.completedTutorials = newData.completedTutorials || [];
1599
+
1600
+ // Appliquer les récompenses directement sur l'objet newData
1601
+ if (xpBonus) newData.xp += xpBonus;
1602
+ if (achievement && !newData.achievements.includes(achievement)) newData.achievements.push(achievement);
1603
+ if (skill) {
1604
+ const existingSkill = newData.skills.find(s => s.name === skill.name);
1605
+ if (existingSkill) {
1606
+ existingSkill.points += skill.points;
1607
+ } else {
1608
+ newData.skills.push({ name: skill.name, points: skill.points });
1609
+ }
1610
+ }
1611
+
1612
+ newData.completedTutorials.push(tutorialId);
1613
+ newData.activeTutorial = null;
1614
+
1615
+ await engine.userProvider.updateUser(user, newData);
1616
+
1617
+ const translatedNotification = {
1618
+ title: i18n.t(notification.title, notification.title),
1619
+ message: i18n.t(notification.message, notification.message)
1620
+ };
1621
+
1622
+ res.json({
1623
+ success: true,
1624
+ userUpdate: newData, // Renvoyer l'objet utilisateur complet et mis à jour
1625
+ notification: translatedNotification
1626
+ });
1627
+
1628
+ } catch (error) {
1629
+ console.error('[Tutoriel Rewards Error]', error);
1630
+ res.status(500).json({ error: 'Erreur lors de l\'attribution des récompenses.', details: error.message });
1631
+ }
1632
+ });
1633
+
1510
1634
  engine.get('/api/import/progress/:jobId', [middlewareAuthenticator], async (req, res) => {
1511
1635
  const { jobId } = req.params;
1512
1636
  const user = req.me;
@@ -3365,6 +3489,24 @@ async function insertAndResolveRelations(doc, model, collection, me, idMap) {
3365
3489
  return existingDoc._id;
3366
3490
  }
3367
3491
 
3492
+ for (const field of model.fields) {
3493
+ if (field.type === 'relation' && field.relationFilter && docToProcess[field.name]) {
3494
+ const relatedIds = Array.isArray(docToProcess[field.name]) ? docToProcess[field.name] : [docToProcess[field.name]];
3495
+ for (const id of relatedIds) {
3496
+ const targetCollection = await getCollectionForUser(me, field.targetModel);
3497
+ const validationQuery = {
3498
+ _id: new ObjectId(id), // L'ID doit correspondre
3499
+ ...field.relationFilter // ET le document doit respecter le filtre
3500
+ };
3501
+ const relatedDoc = await targetCollection.findOne(validationQuery);
3502
+ if (!relatedDoc) {
3503
+ // Si on ne trouve rien, c'est que l'ID est invalide ou ne respecte pas le filtre.
3504
+ throw new Error(`La valeur '${id}' pour le champ '${field.name}' ne respecte pas le filtre de relation défini.`);
3505
+ }
3506
+ }
3507
+ }
3508
+ }
3509
+
3368
3510
  // Insertion en conservant éventuellement l'ID original
3369
3511
  const result = docToProcess._id
3370
3512
  ? await collection.insertOne(docToProcess)
@@ -3584,6 +3726,33 @@ const internalEditOrPatchData = async (modelName, filter, data, files, user, isP
3584
3726
  }
3585
3727
  }
3586
3728
 
3729
+ for (const field of model.fields) {
3730
+ // On ne vérifie que si un champ de relation avec un filtre est en cours de modification.
3731
+ if (field.type === 'relation' && field.relationFilter && updateData[field.name] !== undefined) {
3732
+ const relatedIds = Array.isArray(updateData[field.name])
3733
+ ? updateData[field.name]
3734
+ : (updateData[field.name] ? [updateData[field.name]] : []);
3735
+
3736
+ for (const id of relatedIds) {
3737
+ if (!id || !isObjectId(id)) continue; // Ignorer les valeurs null/invalides
3738
+
3739
+ const targetCollection = await getCollectionForUser(user, field.relation);
3740
+
3741
+ const validationQuery = {
3742
+ _id: new ObjectId(id),
3743
+ ...field.relationFilter
3744
+ };
3745
+
3746
+ const relatedDoc = await targetCollection.findOne(validationQuery);
3747
+
3748
+ if (!relatedDoc) {
3749
+ // Si on ne trouve rien, c'est que l'ID est invalide ou ne respecte pas le filtre.
3750
+ throw new Error(`La valeur '${id}' pour le champ '${field.name}' ne respecte pas le filtre de relation défini.`);
3751
+ }
3752
+ }
3753
+ }
3754
+ }
3755
+
3587
3756
  // 8. Calcul du nouveau hash et préparation des données finales
3588
3757
  const finalStateForHash = { ...existingDocs[0], ...updateData };
3589
3758
  const newHash = getFieldValueHash(model, finalStateForHash);