data-primals-engine 1.7.2 → 1.7.3
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.
- package/README.md +160 -160
- package/client/package-lock.json +8430 -8430
- package/client/src/APIInfo.jsx +1 -1
- package/client/src/App.jsx +2 -1
- package/client/src/App.scss +1635 -1626
- package/client/src/AssistantChat.jsx +1 -0
- package/client/src/CalendarView.jsx +1 -0
- package/client/src/ContentView.jsx +3 -3
- package/client/src/Dashboard.jsx +5 -2
- package/client/src/DashboardChart.jsx +1 -0
- package/client/src/DashboardFlexViewItem.jsx +1 -0
- package/client/src/DashboardHtmlViewItem.jsx +1 -0
- package/client/src/DashboardView.jsx +2 -0
- package/client/src/DataEditor.jsx +0 -1
- package/client/src/DataImporter.jsx +489 -468
- package/client/src/DataLayout.jsx +6 -3
- package/client/src/DataTable.jsx +4 -3
- package/client/src/Dialog.jsx +92 -90
- package/client/src/Dialog.scss +122 -116
- package/client/src/DisplayFlexNodeRenderer.jsx +1 -0
- package/client/src/FlexBuilderControls.jsx +1 -0
- package/client/src/FlexBuilderPreview.jsx +1 -1
- package/client/src/FlexNode.jsx +1 -1
- package/client/src/HistoryDialog.jsx +3 -2
- package/client/src/KPIWidget.jsx +1 -1
- package/client/src/KanbanView.jsx +1 -0
- package/client/src/ModelCreator.jsx +4 -0
- package/client/src/ModelList.jsx +1 -0
- package/client/src/PackGallery.jsx +5 -4
- package/client/src/RTETrans.jsx +1 -1
- package/client/src/RelationField.jsx +2 -0
- package/client/src/RelationSelectorWidget.jsx +2 -0
- package/client/src/RelationValue.jsx +1 -0
- package/client/src/RestoreDialog.jsx +1 -0
- package/client/src/WorkflowEditor.jsx +3 -0
- package/client/src/contexts/CommandContext.jsx +2 -1
- package/client/src/contexts/ModelContext.jsx +3 -3
- package/client/src/hooks/data.js +1 -0
- package/client/src/hooks/useValidation.js +1 -0
- package/client/src/translations.js +24 -24
- package/doc/AI-assistance.md +87 -63
- package/doc/Concepts.md +122 -0
- package/doc/Custom-Endpoints.md +31 -0
- package/doc/Event-system.md +13 -14
- package/doc/Home.md +33 -0
- package/doc/Modules.md +83 -0
- package/doc/Packs-gallery.md +8 -23
- package/doc/Workflows.md +32 -0
- package/doc/automation-workflows.md +141 -102
- package/doc/dashboards-kpis-charts.md +47 -49
- package/doc/data-management.md +126 -120
- package/doc/data-models.md +68 -75
- package/doc/roles-permissions.md +144 -43
- package/doc/sharding-replication.md +158 -0
- package/doc/users.md +54 -30
- package/package.json +1 -1
- package/server.js +37 -37
- package/src/constants.js +7 -8
- package/src/data.js +521 -520
- package/src/email.js +157 -154
- package/src/engine.js +117 -7
- package/src/gameObject.js +6 -0
- package/src/i18n.js +0 -1
- package/src/modules/auth-google/index.js +53 -50
- package/src/modules/bucket.js +346 -339
- package/src/modules/data/data.backup.js +400 -376
- package/src/modules/data/data.cluster.js +410 -42
- package/src/modules/data/data.operations.js +3666 -3635
- package/src/modules/data/data.replication.js +106 -64
- package/src/modules/data/data.routes.js +87 -64
- package/src/modules/data/data.scheduling.js +2 -1
- package/src/modules/file.js +248 -247
- package/src/modules/user.js +11 -1
- package/src/sso.js +91 -25
- package/test/cluster.test.js +221 -0
- package/test/core.test.js +0 -2
- package/test/replication.test.js +163 -0
- package/doc/core-concepts.md +0 -33
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# Sharding & Replication: Scalability and High Availability
|
|
2
|
+
|
|
3
|
+
The `data-primals-engine` integrates a sharding and replication system designed to ensure horizontal scalability and high availability of user data. This mechanism distributes data and requests across a cluster of nodes, ensuring the system remains performant and resilient as the load increases.
|
|
4
|
+
|
|
5
|
+
## Fundamental Concepts
|
|
6
|
+
|
|
7
|
+
The architecture is based on several key concepts:
|
|
8
|
+
|
|
9
|
+
1. **User-Based Sharding**: The basic principle is that all data belonging to a specific user is primarily stored on a single node, designated as their "master" node. This greatly simplifies data consistency and query logic.
|
|
10
|
+
|
|
11
|
+
2. **Consistent Hashing**: To determine which node is the "master" for a given user, the system uses a consistent hashing algorithm based on the `username`. To ensure a balanced distribution of users across the cluster's nodes, even if nodes are added or removed, the system uses **virtual nodes** (vnodes). Each physical node is represented by multiple points on the hash ring, which smooths out data distribution.
|
|
12
|
+
|
|
13
|
+
3. **Lease-Based Mastership**: To avoid "split-brain" situations (where two nodes think they are the master for the same user), the system uses a lease mechanism based on MongoDB. The node designated by the hash must periodically acquire and renew a "lease" (a locked document in the database) to confirm its master status. If a node cannot renew its lease, it stops acting as the master, ensuring that only one master is active at any given time.
|
|
14
|
+
|
|
15
|
+
4. **Asynchronous Replication**: Write operations (create, update, delete) are first validated on the master node. Once the operation is successful, it is added to a replication queue. A background process then sends these operations in batches to the "replica" nodes designated for that user, thus ensuring data redundancy.
|
|
16
|
+
|
|
17
|
+
5. **Smart Replica Selection**: The number of replicas is defined by a replication factor (default is 1 master + 1 replica). Nodes eligible to be a replica are chosen in a "greedy" manner: the system selects the healthy nodes with the most free disk space, thereby promoting a balanced storage load.
|
|
18
|
+
|
|
19
|
+
6. **Gossip Protocol**: The cluster's nodes communicate with each other via a "gossip" protocol. Periodically, each node randomly contacts another node to exchange information about the state of other cluster members (status `UP`, `SUSPECT`, `DOWN`, disk space, etc.). This allows each node to have an up-to-date view of the cluster topology without requiring a central coordinator.
|
|
20
|
+
|
|
21
|
+
## Request Flow
|
|
22
|
+
|
|
23
|
+
Request routing is managed intelligently to optimize performance and resilience.
|
|
24
|
+
|
|
25
|
+
### Write Operations (POST, PUT, DELETE)
|
|
26
|
+
|
|
27
|
+
1. A node receives a write request for a user.
|
|
28
|
+
2. It determines which node is the master for that user.
|
|
29
|
+
3. If the current node is not the master, it relays (proxies) the request to the correct master node.
|
|
30
|
+
4. The master node executes the operation on its local database.
|
|
31
|
+
5. Once the operation is successful, it adds it to a queue for asynchronous replication to the replica nodes.
|
|
32
|
+
6. It returns a success response to the client without waiting for the replication to complete.
|
|
33
|
+
|
|
34
|
+
### Read Operations (GET)
|
|
35
|
+
|
|
36
|
+
1. A node receives a read request.
|
|
37
|
+
2. It determines the list of responsible nodes for the user (the master first, then the replicas).
|
|
38
|
+
3. It attempts to relay the request to the first node on the list (the master).
|
|
39
|
+
4. **In case of failure** (timeout, network error), it automatically tries the next node on the list (a replica).
|
|
40
|
+
5. This "failover" process continues until a node responds successfully or all responsible nodes have failed.
|
|
41
|
+
|
|
42
|
+
This mechanism ensures that reads remain possible even if a user's master node is temporarily unavailable.
|
|
43
|
+
|
|
44
|
+
## Request Flow Diagram
|
|
45
|
+
|
|
46
|
+
The diagram below illustrates how a write request is processed in the cluster.
|
|
47
|
+
|
|
48
|
+
```mermaid
|
|
49
|
+
sequenceDiagram
|
|
50
|
+
participant Client
|
|
51
|
+
participant NodeB as Node B (Replica)
|
|
52
|
+
participant NodeA as Node A (Master for UserX)
|
|
53
|
+
participant MongoDBA as Master DB (on Node A)
|
|
54
|
+
participant MongoDBB as Replica DB (on Node B)
|
|
55
|
+
|
|
56
|
+
Client->>+NodeB: POST /api/data (for UserX)
|
|
57
|
+
NodeB->>NodeB: isSelfMasterForUser("UserX")? -> No
|
|
58
|
+
Note over NodeB: I am not the master. Proxying.
|
|
59
|
+
|
|
60
|
+
NodeB->>+NodeA: PROXY: POST /api/data (for UserX)
|
|
61
|
+
NodeA->>NodeA: isSelfMasterForUser("UserX")? -> Yes
|
|
62
|
+
Note over NodeA: I am the master. Processing request.
|
|
63
|
+
|
|
64
|
+
NodeA->>+MongoDBA: 1. Write data
|
|
65
|
+
MongoDBA-->>-NodeA: Success
|
|
66
|
+
|
|
67
|
+
NodeA->>NodeA: 2. Add to replication queue
|
|
68
|
+
Note over NodeA: { op: 'insert', user: 'UserX', ... }
|
|
69
|
+
|
|
70
|
+
NodeA-->>-NodeB: 200 OK (Response to proxy)
|
|
71
|
+
NodeB-->>-Client: 200 OK (Final response)
|
|
72
|
+
|
|
73
|
+
loop Asynchronous Replication Process
|
|
74
|
+
NodeA->>NodeA: Processing queue
|
|
75
|
+
Note over NodeA: Batch of operations for Node B
|
|
76
|
+
NodeA->>+NodeB: POST /api/internal/replicate
|
|
77
|
+
NodeB->>+MongoDBB: Write replicated data
|
|
78
|
+
MongoDBB-->>-NodeB: Success
|
|
79
|
+
NodeB-->>-NodeA: 200 OK
|
|
80
|
+
end
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Fault Tolerance
|
|
84
|
+
|
|
85
|
+
- **Master Node Failure**: If a master node fails, its lease will expire. Another node (likely a former replica) can then acquire the lease and become the new master for the affected users. Requests will be automatically redirected to this new master.
|
|
86
|
+
- **Replica Node Failure**: The gossip protocol will mark the node as `SUSPECT` and then `DOWN`. The replica selection system will choose another healthy node to maintain the replication factor.
|
|
87
|
+
- **Split-Brain**: The lease system is the primary defense against this scenario. Only the node holding the lease can perform write operations, thus preventing data from diverging.
|
|
88
|
+
|
|
89
|
+
## How to Use This Feature
|
|
90
|
+
|
|
91
|
+
Activating the sharding and replication system requires configuring your application instances to communicate with each other.
|
|
92
|
+
|
|
93
|
+
### Prerequisites
|
|
94
|
+
|
|
95
|
+
You need at least two running instances of the `data-primals-engine` application, each with its own database, accessible via a public URL.
|
|
96
|
+
|
|
97
|
+
### Step 1: Enable the Cluster and Replication Modules
|
|
98
|
+
|
|
99
|
+
In your main server file (e.g., `server.js`), ensure that the `cluster` and `replication` modules are added to the list of modules to be loaded.
|
|
100
|
+
|
|
101
|
+
```javascript
|
|
102
|
+
import { Config, Engine } from 'data-primals-engine';
|
|
103
|
+
|
|
104
|
+
// ... other configurations
|
|
105
|
+
|
|
106
|
+
Config.Set("modules", [
|
|
107
|
+
"mongodb",
|
|
108
|
+
"data",
|
|
109
|
+
"user",
|
|
110
|
+
"cluster", // <-- Enable the cluster module
|
|
111
|
+
"replication" // <-- Enable the replication module
|
|
112
|
+
// ... other modules
|
|
113
|
+
]);
|
|
114
|
+
|
|
115
|
+
const app = express();
|
|
116
|
+
const engine = await Engine.Create({ app });
|
|
117
|
+
engine.start();
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Step 2: Configure Peer Discovery
|
|
121
|
+
|
|
122
|
+
The nodes discover each other via a central discovery endpoint. You must set the `PEERS_ENDPOINT` environment variable in your `.env` file for each node.
|
|
123
|
+
|
|
124
|
+
```env
|
|
125
|
+
PEERS_ENDPOINT=https://my-discovery-service.com/peers.json
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
This endpoint must return a JSON object containing a list of all nodes in the cluster. Each node in the list should have a unique `id` and its public `url`.
|
|
129
|
+
|
|
130
|
+
**Example `peers.json`:**
|
|
131
|
+
```json
|
|
132
|
+
{
|
|
133
|
+
"peers": [
|
|
134
|
+
{ "id": "node-1", "public_domain": "node1.myapp.com", "sharding": true, "replica": true },
|
|
135
|
+
{ "id": "node-2", "public_domain": "node2.myapp.com", "sharding": true, "replica": true },
|
|
136
|
+
{ "id": "node-3", "public_domain": "node3.myapp.com", "sharding": true, "replica": true }
|
|
137
|
+
]
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Step 3: (Optional) Fine-Tune Configuration
|
|
142
|
+
|
|
143
|
+
You can adjust the behavior of the cluster by setting the following configuration values:
|
|
144
|
+
|
|
145
|
+
- **`replicationFactor`**: The total number of copies for each user's data (1 master + N replicas). Default is `2`.
|
|
146
|
+
- **`gossipInterval`**: The interval in milliseconds at which nodes exchange state information. Default is `2000` (2 seconds).
|
|
147
|
+
- **`gossipSuspectTimeout`**: The time in milliseconds after which a non-responsive node is marked as `DOWN`. Default is `10000` (10 seconds).
|
|
148
|
+
|
|
149
|
+
**Example in `server.js`:**
|
|
150
|
+
```javascript
|
|
151
|
+
Config.Set("replicationFactor", 3); // 1 master + 2 replicas
|
|
152
|
+
Config.Set("gossipInterval", 5000); // Gossip every 5 seconds
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Once these steps are completed and your application instances are restarted, they will form a cluster, distribute new user data, and replicate it for high availability.
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
**[Next: Contributing](CONTRIBUTING.md)**
|
package/doc/users.md
CHANGED
|
@@ -1,30 +1,54 @@
|
|
|
1
|
-
# Users: Manage Access to the Platform
|
|
2
|
-
|
|
3
|
-
The `data-primals-engine` includes a robust user management system, allowing you to control access to your data and functionalities. The core of this system is the `user` model, which stores all necessary information about platform users.
|
|
4
|
-
|
|
5
|
-
## The `user` Model
|
|
6
|
-
|
|
7
|
-
The `user` model is a fundamental, system-locked model that defines the attributes of each user account.
|
|
8
|
-
|
|
9
|
-
###
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
1
|
+
# Users: Manage Access to the Platform
|
|
2
|
+
|
|
3
|
+
The `data-primals-engine` includes a robust user management system, allowing you to control access to your data and functionalities. The core of this system is the `user` model, which stores all necessary information about platform users.
|
|
4
|
+
|
|
5
|
+
## The `user` Model
|
|
6
|
+
|
|
7
|
+
The `user` model is a fundamental, system-locked model that defines the attributes of each user account.
|
|
8
|
+
|
|
9
|
+
### The `user` Model Fields
|
|
10
|
+
|
|
11
|
+
| Attribute | Type | Description |
|
|
12
|
+
|:------------------|:-----------------------------------|:--------------------------------------------------------------------------------------------------------|
|
|
13
|
+
| **`username`** | string, required, unique | The unique identifier for the user, used for login. |
|
|
14
|
+
| **`password`** | password | The user's hashed password. |
|
|
15
|
+
| **`gender`** | enum | Optional field for gender, with options like `male`, `female`, `other`, `prefer_not_to_say`. |
|
|
16
|
+
| **`contact`** | relation to `contact` model | Links to a `contact` document for detailed personal information (`firstName`, `lastName`, `email`, etc.). |
|
|
17
|
+
| **`roles`** | multiple relation to `role` model | Assigns one or more roles to the user, determining their permissions. |
|
|
18
|
+
| **`lang`** | relation to `lang` model | Specifies the preferred language for the user interface and content. |
|
|
19
|
+
| **`profilePicture`**| file | Allows users to upload a profile image (supports JPEG and PNG). |
|
|
20
|
+
| **`tokens`** | multiple relation to `token` model | Stores authentication tokens associated with the user. |
|
|
21
|
+
|
|
22
|
+
## User Providers: The Authentication Logic
|
|
23
|
+
|
|
24
|
+
The engine's authentication system is designed to be highly extensible through **User Providers**. A `UserProvider` is a component responsible for the core logic of user management: finding users and validating their credentials. This modular approach allows you to connect `data-primals-engine` to virtually any authentication source.
|
|
25
|
+
|
|
26
|
+
The engine comes with several built-in providers:
|
|
27
|
+
- **`DefaultUserProvider`**: A simple, in-memory provider primarily for demonstration and testing purposes. It allows for quick setup without a database dependency.
|
|
28
|
+
- **`MongoUserProvider`**: The standard production-ready provider. It uses the `user` collection in your MongoDB database to store user accounts and securely validates passwords using `bcrypt`.
|
|
29
|
+
- **`SSOUserProvider`**: A specialized provider that works with the `Sso` component to handle authentication from external Identity Providers like Google, SAML, or Microsoft Azure AD.
|
|
30
|
+
|
|
31
|
+
### Extending with a Custom Provider
|
|
32
|
+
|
|
33
|
+
You can create your own `UserProvider` to integrate with other systems, such as LDAP, a different database, or a custom API. You simply need to create a class that extends the base `UserProvider` and implement its methods (`findUserByUsername`, `validatePassword`, etc.). You can then instruct the engine to use it at startup:
|
|
34
|
+
|
|
35
|
+
```javascript
|
|
36
|
+
// In your main server file
|
|
37
|
+
import { Engine } from 'data-primals-engine';
|
|
38
|
+
import { MyCustomLdapProvider } from './my-ldap-provider.js';
|
|
39
|
+
|
|
40
|
+
const engine = await Engine.Create({ app });
|
|
41
|
+
engine.setUserProvider(new MyCustomLdapProvider(engine));
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### User Authentication
|
|
45
|
+
|
|
46
|
+
The engine provides mechanisms for user authentication, typically involving username/password credentials to issue **JWT (JSON Web Tokens)**. The `UserProvider` is responsible for validating these credentials. Once validated, the issued tokens are used to secure subsequent API requests, ensuring that only authorized users can access or modify data.
|
|
47
|
+
|
|
48
|
+
### User-Specific Data
|
|
49
|
+
|
|
50
|
+
Each document created within the `data-primals-engine` is associated with a user via the `_user` field. This ensures data isolation and allows for granular access control, where users primarily interact with data they own or have been granted access to.
|
|
51
|
+
|
|
52
|
+
Effective user management is crucial for maintaining security and organizing access within your `data-primals-engine` application.
|
|
53
|
+
|
|
54
|
+
**[Next: Roles and Permissions](roles-permissions)**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "data-primals-engine",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.3",
|
|
4
4
|
"description": "data-primals-engine is a package responsible from handling large amount of data using MongoDB in a practical and performant way. It can also get workflow models working (for automation), and fully supports internationalisation. It also has integrated AI assistant.",
|
|
5
5
|
"main": "src/engine.js",
|
|
6
6
|
"type": "module",
|
package/server.js
CHANGED
|
@@ -1,37 +1,37 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
// ===============
|
|
4
|
-
|
|
5
|
-
//set ES modules to be loaded by the script
|
|
6
|
-
import process from "node:process";
|
|
7
|
-
import {Config, Engine, BenchmarkTool, GameObject, Logger} from "./src/index.js";
|
|
8
|
-
import sirv from "sirv";
|
|
9
|
-
import express from "express";
|
|
10
|
-
import {port} from "./src/constants.js";
|
|
11
|
-
|
|
12
|
-
Config.Set("modules", ["mongodb", "data", "file", "bucket", "workflow","user", "assistant", "swagger"])
|
|
13
|
-
Config.Set("middlewares", []);
|
|
14
|
-
Config.Set("useDemoAccounts", true);
|
|
15
|
-
|
|
16
|
-
const bench = GameObject.Create("Benchmark");
|
|
17
|
-
const timer = bench.addComponent(BenchmarkTool);
|
|
18
|
-
timer.start();
|
|
19
|
-
|
|
20
|
-
const app = express();
|
|
21
|
-
const engine = await Engine.Create({app});
|
|
22
|
-
|
|
23
|
-
if (process.argv.length === 3) {
|
|
24
|
-
let arg = process.argv[2];
|
|
25
|
-
if( arg === 'reset-models'){
|
|
26
|
-
console.log("resetting models");
|
|
27
|
-
await engine.resetModels();
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
const realPort = Config.Get('port', process.env.PORT || port);
|
|
33
|
-
engine.start(realPort, async (r) => {
|
|
34
|
-
const logger = engine.getComponent(Logger);
|
|
35
|
-
console.log("Server started on port " + realPort);
|
|
36
|
-
timer.stop();
|
|
37
|
-
});
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
// ===============
|
|
4
|
+
|
|
5
|
+
//set ES modules to be loaded by the script
|
|
6
|
+
import process from "node:process";
|
|
7
|
+
import {Config, Engine, BenchmarkTool, GameObject, Logger} from "./src/index.js";
|
|
8
|
+
import sirv from "sirv";
|
|
9
|
+
import express from "express";
|
|
10
|
+
import {port} from "./src/constants.js";
|
|
11
|
+
|
|
12
|
+
Config.Set("modules", ["mongodb", "data", "file", "bucket", "workflow","user", "assistant", "swagger", "replication", "cluster"])
|
|
13
|
+
Config.Set("middlewares", []);
|
|
14
|
+
Config.Set("useDemoAccounts", true);
|
|
15
|
+
|
|
16
|
+
const bench = GameObject.Create("Benchmark");
|
|
17
|
+
const timer = bench.addComponent(BenchmarkTool);
|
|
18
|
+
timer.start();
|
|
19
|
+
|
|
20
|
+
const app = express();
|
|
21
|
+
const engine = await Engine.Create({app});
|
|
22
|
+
|
|
23
|
+
if (process.argv.length === 3) {
|
|
24
|
+
let arg = process.argv[2];
|
|
25
|
+
if( arg === 'reset-models'){
|
|
26
|
+
console.log("resetting models");
|
|
27
|
+
await engine.resetModels();
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
const realPort = Config.Get('port', process.env.PORT || port);
|
|
33
|
+
engine.start(realPort, async (r) => {
|
|
34
|
+
const logger = engine.getComponent(Logger);
|
|
35
|
+
console.log("Server started on port " + realPort);
|
|
36
|
+
timer.stop();
|
|
37
|
+
});
|
package/src/constants.js
CHANGED
|
@@ -230,12 +230,6 @@ export const databasePoolSize = 30;
|
|
|
230
230
|
export const tlsAllowInvalidCertificates = false;
|
|
231
231
|
export const tlsAllowInvalidHostnames = false;
|
|
232
232
|
|
|
233
|
-
/**
|
|
234
|
-
* Cluster configuration for data federation
|
|
235
|
-
* @type {string[]}
|
|
236
|
-
*/
|
|
237
|
-
export const clusterPeers = (process.env.CLUSTER_PEERS || '').split(',').filter(Boolean);
|
|
238
|
-
|
|
239
233
|
/**
|
|
240
234
|
* Options for the HTML sanitizer
|
|
241
235
|
* @type {{allowedSchemesByTag: {}, selfClosing: string[], allowedSchemes: string[], enforceHtmlBoundary: boolean, disallowedTagsMode: string, allowProtocolRelative: boolean, allowedAttributes: {a: string[], img: string[], code: string[]}, allowedTags: string[], allowedSchemesAppliedToAttributes: string[]}}
|
|
@@ -315,8 +309,12 @@ export const MONGO_CALC_OPERATORS = {
|
|
|
315
309
|
'$regexMatch': {
|
|
316
310
|
label: 'Find by regex',
|
|
317
311
|
description: 'Find a string matching a regular expression (Ecmascript)',
|
|
318
|
-
|
|
319
|
-
|
|
312
|
+
specialStructure: true, // Indique une structure spéciale
|
|
313
|
+
args: [
|
|
314
|
+
{ name: 'input', label: 'Input String', type: 'text', description: 'The string to match against.' },
|
|
315
|
+
{ name: 'regex', label: 'Regex Pattern', type: 'text', description: 'The ECMA-262 regex pattern.' },
|
|
316
|
+
{ name: 'options', label: 'Options', type: 'text', optional: true, description: 'Regex options (e.g., "i" for case-insensitivity).' }
|
|
317
|
+
]
|
|
320
318
|
},
|
|
321
319
|
$and: {
|
|
322
320
|
label: 'Et (and)',
|
|
@@ -483,6 +481,7 @@ export const MONGO_CALC_OPERATORS = {
|
|
|
483
481
|
$toString: {label: 'toString', multi: false, converter: true},
|
|
484
482
|
$toInt: {label: 'toInt', multi: false, converter: true},
|
|
485
483
|
$toDouble: {label: 'toDouble', multi: false, converter: true},
|
|
484
|
+
$toDate: {label: 'toDate', multi: false, converter: true},
|
|
486
485
|
|
|
487
486
|
// --- Special Query Operators (not for $expr) ---
|
|
488
487
|
// These operators are handled by a standard $match stage, not inside $expr.
|