data-primals-engine 1.6.3 → 1.7.0

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 (55) hide show
  1. package/README.md +52 -900
  2. package/client/index.js +3 -0
  3. package/client/package-lock.json +7563 -8811
  4. package/client/package.json +11 -1
  5. package/client/src/App.scss +29 -0
  6. package/client/src/AssistantChat.jsx +369 -362
  7. package/client/src/DataEditor.jsx +383 -383
  8. package/client/src/DataLayout.jsx +54 -20
  9. package/client/src/ModelList.jsx +280 -280
  10. package/client/src/ViewSwitcher.scss +0 -31
  11. package/client/src/_variables.scss +3 -0
  12. package/client/src/constants.js +81 -100
  13. package/client/src/contexts/CommandContext.jsx +274 -259
  14. package/client/vite.config.js +30 -30
  15. package/doc/AI-assistance.md +93 -0
  16. package/doc/Advanced-workflows.md +90 -0
  17. package/doc/Event-system.md +79 -0
  18. package/doc/Packs-gallery.md +73 -0
  19. package/doc/automation-workflows.md +102 -0
  20. package/doc/core-concepts.md +33 -0
  21. package/doc/custom-api-endpoints.md +40 -0
  22. package/doc/dashboards-kpis-charts.md +49 -0
  23. package/doc/data-management.md +120 -0
  24. package/doc/data-models.md +75 -0
  25. package/doc/index.md +14 -0
  26. package/doc/roles-permissions.md +43 -0
  27. package/doc/users.md +30 -0
  28. package/package.json +20 -10
  29. package/src/client.js +6 -4
  30. package/src/constants.js +1 -1
  31. package/src/core.js +31 -12
  32. package/src/defaultModels.js +1 -1
  33. package/src/engine.js +342 -335
  34. package/src/filter.js +72 -173
  35. package/src/migrate.js +1 -1
  36. package/src/modules/assistant/assistant.js +30 -20
  37. package/src/modules/data/data.backup.js +4 -4
  38. package/src/modules/data/data.js +8 -7
  39. package/src/modules/data/data.operations.js +186 -133
  40. package/src/modules/data/data.relations.js +3 -2
  41. package/src/modules/data/data.scheduling.js +1 -1
  42. package/src/modules/mongodb.js +17 -8
  43. package/src/modules/swagger.js +25 -5
  44. package/src/modules/user.js +108 -79
  45. package/src/modules/workflow.js +138 -3
  46. package/src/packs.js +5697 -5697
  47. package/src/profiles.js +19 -0
  48. package/swagger-en.yml +3391 -1550
  49. package/swagger-fr.yml +3385 -2896
  50. package/test/assistant.test.js +2 -2
  51. package/test/core.test.js +341 -0
  52. package/test/data.backup.integration.test.js +3 -1
  53. package/test/data.history.integration.test.js +0 -1
  54. package/test/data.integration.test.js +137 -2
  55. package/test/user.test.js +33 -29
@@ -0,0 +1,120 @@
1
+ # Data Management: Create, Read, Update, and Delete Entries
2
+
3
+ The `data-primals-engine` provides a powerful and flexible API for performing standard CRUD (Create, Read, Update, Delete) operations on all defined data models. These generic endpoints allow you to interact with your data programmatically.
4
+
5
+ ## Authentication
6
+
7
+ All data management operations require authentication. You must provide a valid `_user` query parameter (your username) and a `Bearer` token in the `Authorization` header for most operations.
8
+
9
+ ## API Endpoints Overview
10
+
11
+ The following endpoints are available for generic data management:
12
+
13
+ ### 1. Create Data: `POST /api/data`
14
+
15
+ This endpoint allows you to create one or more new documents within a specified model.
16
+
17
+ - **Method**: `POST`
18
+ - **Summary**: Create one or more documents
19
+ - **Description**: Creates one or more new documents in a specified model.
20
+ - **Security**: `BearerAuth`
21
+ - **Parameters**:
22
+ - `_user` (query, required): Your username for authentication.
23
+ - `model` (body, required): The name of the model in which to create the documents (e.g., 'user', 'product').
24
+ - `data` (body, required): The data to insert. Can be a single object or an array of objects. Using the `$find` operator is recommended for relational data.
25
+ - `lang` (query, optional, default: 'en'): Language used for error messages.
26
+ - **Example Request Body**:
27
+ ```json
28
+ {
29
+ "model": "product",
30
+ "data": {
31
+ "name": "New Product",
32
+ "price": 99.99,
33
+ "currency": "60d0fe4f5311236168a109cb"
34
+ }
35
+ }
36
+ ```
37
+ - **Responses**: `201` (Document(s) successfully created), `400` (Invalid data), `401` (Unauthorized).
38
+
39
+ ### 2. Search Data: `POST /api/data/search`
40
+
41
+ This endpoint allows you to search and retrieve documents from a specified model. It supports powerful filtering, sorting, pagination, and relation population.
42
+
43
+ - **Method**: `POST`
44
+ - **Summary**: Search among data
45
+ - **Description**: Search across all data of the specified model.
46
+ - **Security**: `BearerAuth`
47
+ - **Parameters**:
48
+ - `_user` (query, required): Your username for authentication.
49
+ - `model` (body, required): The name of the data model (e.g., 'user', 'product').
50
+ - `filter` (body, optional): MongoDB filter JSON object for the search.
51
+ - `sort` (query, optional): Sort parameter by field (e.g., `fieldName:ASC;fieldName2:DESC`).
52
+ - `limit` (query, optional, default: 1000): Maximum number of documents to return.
53
+ - `offset` (query, optional, default: 0): Number of documents to skip (for pagination).
54
+ - `depth` (query, optional, default: 1): Population depth for 'relation' type fields.
55
+ - `lang` (query, optional, default: 'en'): Language used for error messages.
56
+ - **Example Request Body (Filter)**:
57
+ ```json
58
+ {
59
+ "model": "product",
60
+ "filter": {
61
+ "price": { "$gt": 50 },
62
+ "category": "60d0fe4f5311236168a109cc"
63
+ }
64
+ }
65
+ ```
66
+ - **Responses**: `200` (Success with returned data), `401` (Unauthorized).
67
+
68
+ ### 3. Update Data: `PUT /api/data/{id}` or `PUT /api/data` (Bulk)
69
+
70
+ You can update a single document by its ID or perform bulk updates using a filter.
71
+
72
+ - **Method**: `PUT`
73
+ - **Summary**: Update a document (by ID) or Bulk update documents
74
+ - **Description**: Updates an existing document using its ID, or multiple documents using a filter.
75
+ - **Security**: `BearerAuth`
76
+ - **Parameters**:
77
+ - `_user` (query, required): Your username for authentication.
78
+ - `id` (path, required for single update): The unique identifier (`_id`) of the document to update.
79
+ - `model` (body, required): The name of the data model.
80
+ - `data` (body, required): The data to edit. For bulk updates, this object will contain the fields to update.
81
+ - `filter` (body, optional, for bulk update): MongoDB filter JSON object to select documents for bulk update.
82
+ - `lang` (query, optional, default: 'en'): Language used for error messages.
83
+ - **Example Request Body (Single Update)**:
84
+ ```json
85
+ {
86
+ "model": "product",
87
+ "data": {
88
+ "price": 120.00
89
+ }
90
+ }
91
+ ```
92
+ - **Responses**: `200` (Document successfully updated), `400` (Invalid data), `401` (Unauthorized), `404` (Document not found).
93
+
94
+ ### 4. Delete Data: `DELETE /api/data`
95
+
96
+ This endpoint allows you to permanently delete one or more documents.
97
+
98
+ - **Method**: `DELETE`
99
+ - **Summary**: Delete one or more document(s)
100
+ - **Description**: Permanently deletes a document using its ID, or multiple documents using a filter.
101
+ - **Security**: `BearerAuth`
102
+ - **Parameters**:
103
+ - `_user` (query, required): Your username for authentication.
104
+ - `ids` (body, optional): An array of identifiers of the documents to delete.
105
+ - `filter` (body, optional): The MongoDB JSON filter to apply for bulk deletion.
106
+ - `lang` (query, optional, default: 'en'): Language used for error messages.
107
+ - **Example Request Body (Bulk Delete)**:
108
+ ```json
109
+ {
110
+ "model": "product",
111
+ "filter": {
112
+ "status": "draft"
113
+ }
114
+ }
115
+ ```
116
+ - **Responses**: `200` (Document successfully deleted), `401` (Unauthorized), `404` (Document not found).
117
+
118
+ These generic CRUD endpoints provide a flexible and powerful way to interact with all your data models within the `data-primals-engine`.
119
+
120
+ **Next: Dashboards, KPIs, and Charts**
@@ -0,0 +1,75 @@
1
+ # Data Models: Structuring Your Information
2
+
3
+ Data Models are the fundamental building blocks in `data-primals-engine`, defining how your application's data is structured and stored. They are essentially blueprints for collections of documents, enabling you to organize and manage diverse types of information.
4
+
5
+ ## What is a Data Model?
6
+
7
+ In `data-primals-engine`, a data model is a flexible definition of a data entity. Unlike traditional relational databases, models here are schema-less (thanks to MongoDB), meaning you can evolve their structure over time without rigid migration processes. Each model corresponds to a collection in your MongoDB database.
8
+
9
+ ## Defining a Model
10
+
11
+ Models can be defined either through the platform's user interface or by providing a JSON schema. Key attributes of a model include:
12
+
13
+ - **`name`** (string, unique): The technical name of the model (e.g., `product`, `user`, `order`). This is used for API interactions and internal references.
14
+ - **`description`** (string): A brief explanation of the model's purpose.
15
+ - **`icon`** (string): An icon (e.g., a Font Awesome class) to visually represent the model in the UI.
16
+ - **`tags`** (array of strings): Keywords for categorization and filtering.
17
+ - **`locked`** (boolean): Indicates if the model is a system model and cannot be modified or deleted via the standard UI (e.g., `user`, `permission`).
18
+ - **`fields`** (array of objects): The core of the model, defining its attributes.
19
+
20
+ ## Fields: The Attributes of a Model
21
+
22
+ Each field within a model defines a specific piece of data. Fields have various properties to control their type, behavior, and validation:
23
+
24
+ - **`name`** (string, unique within model): The name of the attribute (e.g., `title`, `price`, `email`).
25
+ - **`type`** (string, required): The data type of the field. Common types include:
26
+ - `string`, `string_t` (translatable string)
27
+ - `number`
28
+ - `boolean`
29
+ - `datetime`, `date`
30
+ - `email`, `url`, `phone`, `password`
31
+ - `richtext`, `richtext_t` (translatable rich text)
32
+ - `enum` (predefined list of values)
33
+ - `file` (for file uploads)
34
+ - `relation` (to link to another model)
35
+ - `array` (for lists of values or sub-documents)
36
+ - `code` (for storing code snippets, e.g., JSON, JavaScript)
37
+ - **`required`** (boolean): If `true`, the field must have a value.
38
+ - **`unique`** (boolean): If `true`, the field's value must be unique across all documents in the collection.
39
+ - **`default`**: A default value for the field.
40
+ - **`min`, `max`**: Minimum and maximum values for `number` fields, or length for `string` fields.
41
+ - **`relation`** (string, for `relation` type): The name of the model this field relates to.
42
+ - **`multiple`** (boolean, for `relation` type): If `true`, the field can relate to multiple documents in the target model.
43
+ - **`hint`** (string): A helpful description displayed in the UI.
44
+
45
+ ## Example: The `product` Model
46
+
47
+ The `product` model, defined in `defaultModels.js`, illustrates how fields are used to structure information about a product:
48
+
49
+ ```javascript
50
+ product: {
51
+ name: 'product',
52
+ "icon": "FaShoppingBag",
53
+ "description": "",
54
+ "tags": ["ecommerce", "products"],
55
+ fields: [
56
+ { name: 'name', type: 'string_t', required: true },
57
+ { name: 'image', type: 'array', itemsType: 'file', mimeTypes: ['image/jpeg', 'image/png', 'image/gif', 'image/webp'] },
58
+ { name: 'description', type: 'richtext_t' },
59
+ { name: 'price', type: 'number', required: true },
60
+ { name: 'currency', type: 'relation', relation: 'currency', required: true },
61
+ { name: 'billingFrequency', type: 'enum', items: ['none', 'monthly', 'yearly'] },
62
+ { name: 'slug', type: 'string', required: true, unique: true },
63
+ { name: 'brand', type: 'relation', relation: 'brand' },
64
+ { name: 'category', type: 'relation', relation: 'taxonomy' },
65
+ { name: 'seoTitle', type: 'string_t' },
66
+ { name: 'seoDescription', type: 'string_t' }
67
+ ]
68
+ },
69
+ ```
70
+
71
+ This example shows how a `product` can have a translatable `name`, multiple `image` files, a `price` with a `currency` relation, and be linked to a `brand` and `category` (taxonomy).
72
+
73
+ By defining models and their fields, you create a robust and adaptable data foundation for your `data-primals-engine` application.
74
+
75
+ **Next: Data Management**
package/doc/index.md ADDED
@@ -0,0 +1,14 @@
1
+ # data-primals-engine Documentation
2
+
3
+ Welcome to the `data-primals-engine` documentation! This guide will help you understand the core concepts, features, and how to effectively use the platform to build powerful data-driven applications.
4
+
5
+ ## Table of Contents
6
+
7
+ - Core Concepts: Data Modeling Fundamentals
8
+ - Data Models: Structuring Your Information
9
+ - Data Management: Create, Read, Update, and Delete Entries
10
+ - Custom API Endpoints: Create Dynamic HTTP Routes
11
+ - Dashboards, KPIs, and Charts: Track Your Key Metrics
12
+ - Users: Manage Access to the Platform
13
+ - Roles and Permissions: Define Who Can See and Do What
14
+ - Automation with Workflows: Create Automated Processes
@@ -0,0 +1,43 @@
1
+ # Roles and Permissions: Define Who Can See and Do What
2
+
3
+ The `data-primals-engine` implements a robust Role-Based Access Control (RBAC) system to manage user authorizations. This system relies on two core models: `role` and `permission`, allowing for granular control over what users can access and perform within the platform.
4
+
5
+ ## Permissions
6
+
7
+ A **Permission** defines a specific action or access right within the system. Permissions can be very broad (e.g., "admin.full_access") or highly specific (e.g., "product.edit").
8
+
9
+ ### Key Fields of the `permission` Model:
10
+
11
+ - **`name`** (string, required): A unique identifier for the permission (e.g., `model.create`, `product.read`, `user.delete`).
12
+ - **`description`** (richtext, optional): A detailed explanation of what the permission grants.
13
+ - **`filter`** (code - JSON, optional): A JSON filter that restricts the scope of this permission. This is a powerful feature for implementing granular access control. For example, a `product.edit` permission could have a filter `{ "owner": "{_user}" }` to allow a user to only edit products they own. The target model is typically deduced from the permission name (e.g., `product.edit` implies the `product` model).
14
+
15
+ ## Roles
16
+
17
+ A **Role** is a collection of permissions. Instead of assigning individual permissions to each user, you assign roles, which simplifies management. A user can have multiple roles.
18
+
19
+ ### Key Fields of the `role` Model:
20
+
21
+ - **`name`** (string, required, unique): The name of the role (e.g., `Administrator`, `Editor`, `Viewer`).
22
+ - **`permissions`** (multiple relation to `permission` model): A list of `permission` documents associated with this role. Any user assigned this role will inherit all its permissions.
23
+
24
+ ## How RBAC Works
25
+
26
+ 1. **Define Permissions**: Create specific `permission` documents for every action or resource you want to control. Use the `filter` field for fine-grained control.
27
+ 2. **Create Roles**: Group relevant permissions into `role` documents.
28
+ 3. **Assign Roles to Users**: Assign one or more `role` documents to each `user` document.
29
+
30
+ When a user attempts an action (e.g., accessing an API endpoint or modifying a data entry), the system checks if the user's assigned roles grant them the necessary permissions. If a permission has a `filter`, that filter is applied to the data access query, ensuring the user only interacts with allowed subsets of data.
31
+
32
+ ### User Permissions (Exceptions)
33
+
34
+ The `userPermission` model allows for exceptions to the standard role-based permissions. This model can grant or revoke specific permissions for an individual user, either permanently or temporarily.
35
+
36
+ - **`user`** (relation to `user` model): The user for whom the exception applies.
37
+ - **`permission`** (relation to `permission` model): The specific permission being granted or revoked.
38
+ - **`isGranted`** (boolean, required): `true` to grant the permission, `false` to explicitly revoke it.
39
+ - **`expiresAt`** (datetime, optional): If set, the exception is temporary.
40
+
41
+ This comprehensive RBAC system ensures that your `data-primals-engine` application remains secure and that users only have access to the functionalities and data they are authorized to use.
42
+
43
+ **Next: Automation with Workflows**
package/doc/users.md ADDED
@@ -0,0 +1,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
+ ### Key Fields of the `user` Model:
10
+
11
+ - **`username`** (string, required, unique): The unique identifier for the user, used for login.
12
+ - **`password`** (password): The user's hashed password.
13
+ - **`gender`** (enum): Optional field for gender, with options like `male`, `female`, `other`, `prefer_not_to_say`.
14
+ - **`contact`** (relation to `contact` model): Links to a `contact` document, which can store detailed personal information like `firstName`, `lastName`, `email`, and `phone`.
15
+ - **`roles`** (multiple relation to `role` model): Assigns one or more roles to the user, determining their permissions within the system.
16
+ - **`lang`** (relation to `lang` model): Specifies the preferred language for the user interface and content.
17
+ - **`profilePicture`** (file): Allows users to upload a profile image (supports JPEG and PNG).
18
+ - **`tokens`** (multiple relation to `token` model): Stores authentication tokens associated with the user.
19
+
20
+ ### User Authentication
21
+
22
+ The engine provides mechanisms for user authentication, typically involving username/password credentials to issue JWT (JSON Web Tokens). These tokens are then used to secure API requests, ensuring that only authorized users can access or modify data.
23
+
24
+ ### User-Specific Data
25
+
26
+ 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.
27
+
28
+ Effective user management is crucial for maintaining security and organizing access within your `data-primals-engine` application.
29
+
30
+ **Next: Roles and Permissions**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "data-primals-engine",
3
- "version": "1.6.3",
3
+ "version": "1.7.0",
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",
@@ -28,14 +28,18 @@
28
28
  "@rollup/rollup-linux-x64-gnu": "4.6.1"
29
29
  },
30
30
  "resolutions": {
31
- "on-headers": "1.1.0",
32
- "brace-expansion": "2.0.2",
33
- "prismjs": "1.30.0",
31
+ "on-headers": ">=1.1.0",
32
+ "brace-expansion": ">=2.0.2",
33
+ "prismjs": ">=1.30.0",
34
34
  "xml2js": ">=0.5.0",
35
35
  "tar-fs": ">=3.1.1",
36
36
  "vite": ">=7.0.8",
37
37
  "node-forge": ">=1.3.2",
38
- "js-yaml": ">=4.1.1"
38
+ "js-yaml": ">=4.1.1",
39
+ "mdast-util-to-hast": ">=13.2.1",
40
+ "jws": ">=3.2.3",
41
+ "qs": ">=6.14.1",
42
+ "undici": ">=6.23.0"
39
43
  },
40
44
  "overrides": {
41
45
  "react-syntax-highlighter": {
@@ -46,6 +50,12 @@
46
50
  },
47
51
  "refractor": {
48
52
  "prismjs": "1.30.0"
53
+ },
54
+ "body-parser": {
55
+ "qs": ">=6.14.1"
56
+ },
57
+ "stripe": {
58
+ "qs": ">=6.14.1"
49
59
  }
50
60
  },
51
61
  "repository": {
@@ -61,11 +71,11 @@
61
71
  "./*": "./src/*.js"
62
72
  },
63
73
  "dependencies": {
64
- "@langchain/core": "^0.3.79",
74
+ "@langchain/core": "^0.3.80",
65
75
  "archiver": "^7.0.1",
66
76
  "aws-sdk": "^2.1692.0",
67
77
  "bcrypt": "^6.0.0",
68
- "body-parser": "^2.2.1",
78
+ "body-parser": ">=2.2.1",
69
79
  "chalk": "^5.4.1",
70
80
  "check-disk-space": "^3.4.0",
71
81
  "compression": "^1.8.1",
@@ -86,7 +96,7 @@
86
96
  "mongodb": "^6.18.0",
87
97
  "node-cache": "^5.1.2",
88
98
  "node-schedule": "^2.1.1",
89
- "nodemailer": "^7.0.10",
99
+ "nodemailer": "^7.0.11",
90
100
  "openai": "^6.9.1",
91
101
  "passport": "^0.7.0",
92
102
  "passport-saml-encrypted": "^0.1.13",
@@ -101,14 +111,14 @@
101
111
  "sirv": "^3.0.2",
102
112
  "stripe": "^20.0.0",
103
113
  "swagger-ui-express": "^5.0.1",
104
- "tar": "^7.5.2",
114
+ "tar": "7.5.4",
105
115
  "tinycolor2": "^1.6.0",
106
116
  "uniqid": "^5.4.0",
107
117
  "vitest": "^3.2.4",
108
118
  "yaml": "^2.8.1"
109
119
  },
110
120
  "peerDependencies": {
111
- "express": "^5.1.0",
121
+ "express": "^5.2.1",
112
122
  "passport-azure-ad": "^4.3.5",
113
123
  "passport-google-oauth20": "^2.0.0",
114
124
  "react": "18.3.1",
package/src/client.js CHANGED
@@ -1,4 +1,6 @@
1
- // data-primals-engine/client
2
- // Ce fichier sert de point d'entrée pour les modules qui peuvent être utilisés en toute sécurité côté client (navigateur).
3
-
4
- export { Event } from './events.js';
1
+ // data-primals-engine/client
2
+ // Ce fichier sert de point d'entrée pour les modules qui peuvent être utilisés en toute sécurité côté client (navigateur).
3
+
4
+ export { Event } from './events.js';
5
+ export { GameObject, Logger, BenchmarkTool } from './gameObject.js';
6
+ export { Config } from './config.js';
package/src/constants.js CHANGED
@@ -277,7 +277,7 @@ metaModels['erp'] = { load: [ 'accountingExercise', 'accountingLineItem', 'accou
277
277
  * Available model field attributes
278
278
  * @type {string[]}
279
279
  */
280
- export const allowedFields = ['locked', 'hiddenable', 'anonymized', 'condition', 'color', 'index', 'indexType', 'type', 'required', 'hint', 'default', 'validate', 'unique', 'name', 'placeholder', 'asMain'];
280
+ export const allowedFields = ['locked', 'hiddenable', 'encrypted', 'anonymized', 'condition', 'color', 'index', 'indexType', 'type', 'required', 'hint', 'default', 'validate', 'unique', 'name', 'placeholder', 'asMain'];
281
281
 
282
282
 
283
283
 
package/src/core.js CHANGED
@@ -40,7 +40,10 @@ export const isUnsecureKey = (key) => {
40
40
  export const parseSafeJSON = (json) => JSON.parse(json, (key, value) => isUnsecureKey(key) ? undefined : value);
41
41
 
42
42
 
43
- export const isDate = dt => String(new Date(dt)) !== 'Invalid Date'
43
+ export const isDate = dt => {
44
+ if (dt === null || typeof dt === 'undefined') return false;
45
+ return String(new Date(dt)) !== 'Invalid Date';
46
+ };
44
47
 
45
48
  export const safeAssignObject = (obj, key, value) => {
46
49
  if( !isUnsecureKey(key)){
@@ -157,11 +160,11 @@ export function isPathRelativeTo(dir, parent) {
157
160
  * @param value string value
158
161
  */
159
162
  export function isGUID(value) {
160
- return typeof(value) === 'string' && value.match(/^[a-zA-Z0-9]{8}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{12}$/);
163
+ return !!(typeof(value) === 'string' && value.match(/^[a-zA-Z0-9]{8}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{12}$/));
161
164
  }
162
165
 
163
166
  export function isPlainObject(obj) {
164
- return typeof obj === 'object' && obj !== null;
167
+ return typeof obj === 'object' && obj !== null && !Array.isArray(obj) && !(obj instanceof Date);
165
168
  }
166
169
 
167
170
  export function escapeRegExp(string) {
@@ -210,7 +213,11 @@ function splitmix32(a) {
210
213
  }
211
214
 
212
215
 
213
- export const getRand = () =>splitmix32(seed);
216
+ export const getRand = () => {
217
+ const result = splitmix32(seed);
218
+ seed++; // Simple increment to change the state for the next call
219
+ return result;
220
+ };
214
221
 
215
222
  const MAX_RANGE_SIZE = 2n ** 64n
216
223
  const buffer = new BigUint64Array(512)
@@ -371,14 +378,26 @@ export const event_off = (name, callback) => {
371
378
  };
372
379
 
373
380
 
374
- export function slugify(str,replacer='-', replaceUnicode=false) {
375
- str = str.replace(/^\s+|\s+$/g, ''); // trim leading/trailing white space
376
- str = str.toLowerCase(); // convert string to lowercase
377
- if( replaceUnicode)
378
- str = str.replace(/[^a-z0-9 -]/g, ''); // remove any non-alphanumeric characters
379
- str = str.replace(/\s+/g, replacer) // replace spaces with hyphens
380
- .replace(/-+/g, replacer); // remove consecutive hyphens
381
- return str;
381
+ export function slugify(str,replacer='-', removeNonAscii=false) {
382
+
383
+ if (!str) return '';
384
+
385
+ // 1. Convert to string, lowercase, and trim whitespace.
386
+ str = str.toString().toLowerCase().trim();
387
+
388
+ // 2. Normalize Unicode characters (e.g., è -> e). This is now always done.
389
+ str = str.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
390
+
391
+ // 3. Remove any remaining non-ASCII characters if the flag is set.
392
+ if (removeNonAscii) {
393
+ str = str.replace(/[^a-z0-9\s-]/g, '');
394
+ }
395
+
396
+ // 4. Replace spaces with the replacer and clean up consecutive/trailing replacers.
397
+ return str
398
+ .replace(/\s+/g, replacer) // Replace spaces with the replacer.
399
+ .replace(new RegExp(`[^a-z0-9${replacer}]`, 'g'), '') // Remove any character that is not a letter, a number, or the replacer itself.
400
+ .replace(new RegExp(`${replacer}+`, 'g'), replacer); // Replace multiple replacers with a single one.
382
401
  }
383
402
 
384
403
  // resource : https://stackoverflow.com/questions/190852/how-can-i-get-file-extensions-with-javascript
@@ -303,7 +303,7 @@ export const defaultModels = {
303
303
  "icon": "FaTags",
304
304
  "description": "",
305
305
  "tags": ["cms", "organization"],
306
- fields: [
306
+ "fields": [
307
307
  { name: 'name', type: 'string_t', required: true, color: '#71A314' },
308
308
  { name: 'parent', type: 'relation', relation: 'taxonomy', color: '#233607' }, // Relation vers la taxonomie parente
309
309
  { name: 'type', type: 'enum', items: ['keyword', 'category'], color: '#BFBFBF' },