@medyll/idae-machine 0.87.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.
- package/README.md +230 -0
- package/dist/db/dataModel.d.ts +23 -0
- package/dist/db/dataModel.js +40 -0
- package/dist/db/dbFields.d.ts +130 -0
- package/dist/db/dbFields.js +606 -0
- package/dist/db/dbSchema.d.ts +456 -0
- package/dist/db/dbSchema.js +456 -0
- package/dist/form/CollectionButton.svelte +26 -0
- package/dist/form/CollectionButton.svelte.d.ts +22 -0
- package/dist/form/CollectionFieldGuess.svelte +29 -0
- package/dist/form/CollectionFieldGuess.svelte.d.ts +11 -0
- package/dist/form/CollectionFks.svelte +24 -0
- package/dist/form/CollectionFks.svelte.d.ts +9 -0
- package/dist/form/CollectionList.svelte +93 -0
- package/dist/form/CollectionList.svelte.d.ts +30 -0
- package/dist/form/CollectionListMenu.svelte +46 -0
- package/dist/form/CollectionListMenu.svelte.d.ts +27 -0
- package/dist/form/CollectionReverseFks.svelte +56 -0
- package/dist/form/CollectionReverseFks.svelte.d.ts +18 -0
- package/dist/form/CreateUpdate.svelte +191 -0
- package/dist/form/CreateUpdate.svelte.d.ts +20 -0
- package/dist/form/CrudZone.svelte +23 -0
- package/dist/form/CrudZone.svelte.d.ts +22 -0
- package/dist/form/DataProvider.svelte +20 -0
- package/dist/form/DataProvider.svelte.d.ts +9 -0
- package/dist/form/FieldInPlace.svelte +49 -0
- package/dist/form/FieldInPlace.svelte.d.ts +11 -0
- package/dist/form/FieldValue.svelte +213 -0
- package/dist/form/FieldValue.svelte.d.ts +28 -0
- package/dist/form/types.d.ts +17 -0
- package/dist/form/types.js +1 -0
- package/dist/fragments/Confirm.svelte +58 -0
- package/dist/fragments/Confirm.svelte.d.ts +11 -0
- package/dist/fragments/Frame.svelte +19 -0
- package/dist/fragments/Frame.svelte.d.ts +32 -0
- package/dist/fragments/InfoLine.svelte +21 -0
- package/dist/fragments/InfoLine.svelte.d.ts +35 -0
- package/dist/fragments/List.svelte +21 -0
- package/dist/fragments/List.svelte.d.ts +38 -0
- package/dist/fragments/Selector.svelte +26 -0
- package/dist/fragments/Selector.svelte.d.ts +38 -0
- package/dist/fragments/Skeleton.svelte +21 -0
- package/dist/fragments/Skeleton.svelte.d.ts +20 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +23 -0
- package/dist/types/appschemeTypes.d.ts +71 -0
- package/dist/types/appschemeTypes.js +83 -0
- package/package.json +63 -0
|
@@ -0,0 +1,606 @@
|
|
|
1
|
+
/*
|
|
2
|
+
path: D:\boulot\python\wollama\src\lib\db\dbFields.ts
|
|
3
|
+
*/
|
|
4
|
+
import { schemeModel } from './dbSchema';
|
|
5
|
+
export var enumPrimitive;
|
|
6
|
+
(function (enumPrimitive) {
|
|
7
|
+
enumPrimitive["id"] = "id";
|
|
8
|
+
enumPrimitive["any"] = "any";
|
|
9
|
+
enumPrimitive["date"] = "date";
|
|
10
|
+
enumPrimitive["datetime"] = "datetime";
|
|
11
|
+
enumPrimitive["time"] = "time";
|
|
12
|
+
enumPrimitive["text"] = "text";
|
|
13
|
+
enumPrimitive["number"] = "number";
|
|
14
|
+
enumPrimitive["boolean"] = "boolean";
|
|
15
|
+
enumPrimitive["url"] = "url";
|
|
16
|
+
enumPrimitive["email"] = "email";
|
|
17
|
+
enumPrimitive["phone"] = "phone";
|
|
18
|
+
enumPrimitive["password"] = "password";
|
|
19
|
+
})(enumPrimitive || (enumPrimitive = {}));
|
|
20
|
+
export var TplProperties;
|
|
21
|
+
(function (TplProperties) {
|
|
22
|
+
TplProperties["private"] = "private";
|
|
23
|
+
TplProperties["readonly"] = "readonly";
|
|
24
|
+
TplProperties["required"] = "required";
|
|
25
|
+
})(TplProperties || (TplProperties = {}));
|
|
26
|
+
const a = 'any(private required readonly)';
|
|
27
|
+
/*
|
|
28
|
+
renamed from DbCollectionError to IDbErrors
|
|
29
|
+
*/
|
|
30
|
+
class IDbError extends Error {
|
|
31
|
+
code;
|
|
32
|
+
constructor(message, code) {
|
|
33
|
+
super(message);
|
|
34
|
+
this.code = code;
|
|
35
|
+
this.name = 'DbCollectionError';
|
|
36
|
+
}
|
|
37
|
+
static throwError(message, code) {
|
|
38
|
+
throw new IDbError(message, code);
|
|
39
|
+
}
|
|
40
|
+
static handleError(error) {
|
|
41
|
+
if (error instanceof IDbError) {
|
|
42
|
+
console.error(`${error.name}: ${error.message} (Code: ${error.code})`);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
console.error('Unexpected error:', error);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// renammed from IDbFields to IDbCollections
|
|
50
|
+
export class IDbCollections {
|
|
51
|
+
model = schemeModel;
|
|
52
|
+
constructor(model) {
|
|
53
|
+
this.model = schemeModel; //model ?? this.model;
|
|
54
|
+
}
|
|
55
|
+
parseAllCollections() {
|
|
56
|
+
let out = {};
|
|
57
|
+
Object.keys(this.model).forEach((collection) => {
|
|
58
|
+
out[collection] = this.parseRawCollection(collection);
|
|
59
|
+
});
|
|
60
|
+
return out;
|
|
61
|
+
}
|
|
62
|
+
parseRawCollection(collection) {
|
|
63
|
+
const fields = this.getCollectionTemplateFields(collection);
|
|
64
|
+
if (!fields)
|
|
65
|
+
return;
|
|
66
|
+
let out = {};
|
|
67
|
+
Object.keys(fields).forEach((fieldName) => {
|
|
68
|
+
const fieldType = fields[fieldName];
|
|
69
|
+
if (fieldType) {
|
|
70
|
+
out[fieldName] = this.parseCollectionFieldName(collection, fieldName);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
return out;
|
|
74
|
+
}
|
|
75
|
+
parseCollectionFieldName(collection, fieldName) {
|
|
76
|
+
const field = this.#getTemplateFieldRule(collection, fieldName);
|
|
77
|
+
if (!field) {
|
|
78
|
+
IDbError.throwError(`Field ${fieldName} not found in collection ${collection}`, 'FIELD_NOT_FOUND');
|
|
79
|
+
return undefined;
|
|
80
|
+
}
|
|
81
|
+
const fieldType = this.testIs('primitive', field) ??
|
|
82
|
+
this.testIs('array', field) ??
|
|
83
|
+
this.testIs('object', field) ??
|
|
84
|
+
this.testIs('fk', field);
|
|
85
|
+
return this.forge({ collection, fieldName, ...fieldType });
|
|
86
|
+
}
|
|
87
|
+
parsFieldRule(fieldRule) {
|
|
88
|
+
if (!fieldRule)
|
|
89
|
+
return;
|
|
90
|
+
const fieldType = this.testIs('primitive', fieldRule) ??
|
|
91
|
+
this.testIs('array', fieldRule) ??
|
|
92
|
+
this.testIs('object', fieldRule) ??
|
|
93
|
+
this.testIs('fk', fieldRule);
|
|
94
|
+
return fieldType;
|
|
95
|
+
}
|
|
96
|
+
forge({ collection, fieldName, fieldType, fieldRule, fieldArgs, is }) {
|
|
97
|
+
return {
|
|
98
|
+
collection,
|
|
99
|
+
fieldName,
|
|
100
|
+
fieldType,
|
|
101
|
+
fieldRule,
|
|
102
|
+
fieldArgs,
|
|
103
|
+
is
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
#getModel() {
|
|
107
|
+
return this.model;
|
|
108
|
+
}
|
|
109
|
+
getCollection(collection) {
|
|
110
|
+
return this.#getModel()[String(collection)];
|
|
111
|
+
}
|
|
112
|
+
getCollectionTemplate(collection) {
|
|
113
|
+
return this.getCollection(collection)['template'];
|
|
114
|
+
}
|
|
115
|
+
getCollectionTemplateFks(collection) {
|
|
116
|
+
return this.getCollection(collection)['template']?.fks;
|
|
117
|
+
}
|
|
118
|
+
getIndexName(collection) {
|
|
119
|
+
return this.getCollection(collection)?.template?.index;
|
|
120
|
+
}
|
|
121
|
+
getCollectionTemplateFields(collection) {
|
|
122
|
+
return this.getCollectionTemplate(collection)?.fields;
|
|
123
|
+
}
|
|
124
|
+
getTemplatePresentation(collection) {
|
|
125
|
+
return this.getCollectionTemplate(collection)?.presentation;
|
|
126
|
+
}
|
|
127
|
+
#getTemplateFieldRule(collection, fieldName) {
|
|
128
|
+
return this.getCollectionTemplateFields(collection)?.[String(fieldName)];
|
|
129
|
+
}
|
|
130
|
+
getFkFieldType(string) {
|
|
131
|
+
const [collection, field] = string.split('.');
|
|
132
|
+
let template = this.#getTemplateFieldRule(collection, field);
|
|
133
|
+
return template;
|
|
134
|
+
}
|
|
135
|
+
getFkTemplateFields(string) {
|
|
136
|
+
const [collection, field] = string.split('.');
|
|
137
|
+
return this.getCollection(collection).template?.fields;
|
|
138
|
+
}
|
|
139
|
+
testIs(what, fieldRule) {
|
|
140
|
+
const typeMappings = {
|
|
141
|
+
fk: 'fk-',
|
|
142
|
+
array: 'array-of-',
|
|
143
|
+
object: 'object-',
|
|
144
|
+
primitive: ''
|
|
145
|
+
};
|
|
146
|
+
const prefix = typeMappings[what];
|
|
147
|
+
if (fieldRule.startsWith(prefix)) {
|
|
148
|
+
return this.is(what, fieldRule);
|
|
149
|
+
}
|
|
150
|
+
return undefined;
|
|
151
|
+
}
|
|
152
|
+
is(what, fieldRule) {
|
|
153
|
+
return this.extract(what, fieldRule);
|
|
154
|
+
}
|
|
155
|
+
indexValue(collection, data) {
|
|
156
|
+
let presentation = this.getIndexName(collection);
|
|
157
|
+
return data[presentation];
|
|
158
|
+
}
|
|
159
|
+
extract(type, fieldRule) {
|
|
160
|
+
// fieldType
|
|
161
|
+
function extractAfter(pattern, source) {
|
|
162
|
+
// remove all between () on source
|
|
163
|
+
const reg = source?.split('(')?.[0];
|
|
164
|
+
return reg.split(pattern)[1];
|
|
165
|
+
}
|
|
166
|
+
function extractArgs(source) {
|
|
167
|
+
const [piece, remaining] = source.split('(');
|
|
168
|
+
if (!remaining)
|
|
169
|
+
return { piece: piece.trim(), args: undefined };
|
|
170
|
+
const [central] = remaining?.split(')');
|
|
171
|
+
const args = central?.split(' ');
|
|
172
|
+
// console.log({ piece, args });
|
|
173
|
+
return { piece: piece.trim(), args };
|
|
174
|
+
}
|
|
175
|
+
let extractedArgs = extractArgs(fieldRule);
|
|
176
|
+
let fieldType;
|
|
177
|
+
let is = extractedArgs?.piece;
|
|
178
|
+
let fieldArgs = extractedArgs?.args;
|
|
179
|
+
switch (type) {
|
|
180
|
+
case 'array':
|
|
181
|
+
fieldType = extractAfter('array-of-', fieldRule);
|
|
182
|
+
is = is ?? fieldType;
|
|
183
|
+
break;
|
|
184
|
+
case 'object':
|
|
185
|
+
fieldType = extractAfter('object-', fieldRule);
|
|
186
|
+
is = is ?? fieldType;
|
|
187
|
+
break;
|
|
188
|
+
case 'fk':
|
|
189
|
+
fieldType = this.getFkFieldType(extractAfter('fk-', fieldRule));
|
|
190
|
+
is = extractedArgs?.piece;
|
|
191
|
+
break;
|
|
192
|
+
case 'primitive':
|
|
193
|
+
fieldType = extractedArgs?.piece;
|
|
194
|
+
is = is ?? fieldType;
|
|
195
|
+
break;
|
|
196
|
+
}
|
|
197
|
+
return { fieldType, fieldRule, fieldArgs, is: type };
|
|
198
|
+
}
|
|
199
|
+
fks(collection) {
|
|
200
|
+
let fks = this.getCollectionTemplateFks(collection);
|
|
201
|
+
let out = {};
|
|
202
|
+
// loop over fks
|
|
203
|
+
if (fks) {
|
|
204
|
+
Object.keys(fks).forEach((collection) => {
|
|
205
|
+
out[collection] = this.parseRawCollection(collection);
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
return out;
|
|
209
|
+
}
|
|
210
|
+
reverseFks(targetCollection) {
|
|
211
|
+
const result = {};
|
|
212
|
+
Object.entries(this.#getModel()).forEach(([collectionName, collectionModel]) => {
|
|
213
|
+
const template = collectionModel.template;
|
|
214
|
+
if (template && template.fks) {
|
|
215
|
+
Object.entries(template.fks).forEach(([fkName, fkConfig]) => {
|
|
216
|
+
if (fkConfig?.code === targetCollection) {
|
|
217
|
+
if (!result[collectionName]) {
|
|
218
|
+
result[collectionName] = {};
|
|
219
|
+
}
|
|
220
|
+
result[collectionName][fkName] = fkConfig;
|
|
221
|
+
}
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
return result;
|
|
226
|
+
}
|
|
227
|
+
// iterate base
|
|
228
|
+
iterateArrayField(collection, fieldName, data) {
|
|
229
|
+
const fieldInfo = this.parseCollectionFieldName(collection, fieldName);
|
|
230
|
+
if (fieldInfo?.is !== 'array' || !Array.isArray(data)) {
|
|
231
|
+
return [];
|
|
232
|
+
}
|
|
233
|
+
return data.map(() => this.parseCollectionFieldName(collection, fieldName));
|
|
234
|
+
}
|
|
235
|
+
iterateObjectField(collection, fieldName, data) {
|
|
236
|
+
const fieldInfo = this.parseCollectionFieldName(collection, fieldName);
|
|
237
|
+
if (fieldInfo?.is !== 'object' || typeof data !== 'object') {
|
|
238
|
+
return [];
|
|
239
|
+
}
|
|
240
|
+
return Object.keys(data).map((key) => this.parseCollectionFieldName(collection, key));
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
// display field values, based on schema and provided data
|
|
244
|
+
// renamed from iDBFieldValues to iDbCollectionValues
|
|
245
|
+
// path D:\boulot\python\wollama\src\lib\db\dbFields.ts
|
|
246
|
+
export class IDbCollectionValues {
|
|
247
|
+
dbCollections;
|
|
248
|
+
collection;
|
|
249
|
+
constructor(collection) {
|
|
250
|
+
this.collection = collection;
|
|
251
|
+
this.dbCollections = new IDbCollections();
|
|
252
|
+
}
|
|
253
|
+
presentation(data) {
|
|
254
|
+
try {
|
|
255
|
+
this.#checkError(!this.#checkAccess(), 'Access denied', 'ACCESS_DENIED');
|
|
256
|
+
const presentation = this.dbCollections.getTemplatePresentation(this.collection);
|
|
257
|
+
this.#checkError(!presentation, 'Presentation template not found', 'TEMPLATE_NOT_FOUND');
|
|
258
|
+
const fields = presentation.split(' ');
|
|
259
|
+
return fields
|
|
260
|
+
.map((field) => {
|
|
261
|
+
const value = data[field];
|
|
262
|
+
return value !== null && value !== undefined ? String(value) : '';
|
|
263
|
+
})
|
|
264
|
+
.join(' ');
|
|
265
|
+
}
|
|
266
|
+
catch (error) {
|
|
267
|
+
IDbError.handleError(error);
|
|
268
|
+
return '';
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
indexValue(data) {
|
|
272
|
+
try {
|
|
273
|
+
this.#checkError(!this.#checkAccess(), 'Access denied', 'ACCESS_DENIED');
|
|
274
|
+
const indexName = this.dbCollections.getIndexName(this.collection);
|
|
275
|
+
this.#checkError(!indexName, 'Index not found for collection', 'INDEX_NOT_FOUND');
|
|
276
|
+
this.#checkError(!(indexName in data), `Index field ${indexName} not found in data`, 'FIELD_NOT_FOUND');
|
|
277
|
+
return data[indexName];
|
|
278
|
+
}
|
|
279
|
+
catch (error) {
|
|
280
|
+
IDbError.handleError(error);
|
|
281
|
+
return null;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
format(fieldName, data) {
|
|
285
|
+
try {
|
|
286
|
+
this.#checkError(!this.#checkAccess(), 'Access denied', 'ACCESS_DENIED');
|
|
287
|
+
this.#checkError(!(fieldName in data), `Field ${String(fieldName)} not found in data`, 'FIELD_NOT_FOUND');
|
|
288
|
+
const fieldInfo = this.dbCollections.parseCollectionFieldName(this.collection, fieldName);
|
|
289
|
+
this.#checkError(!fieldInfo, `Field ${String(fieldName)} not found in collection`, 'FIELD_NOT_FOUND');
|
|
290
|
+
switch (fieldInfo?.fieldType) {
|
|
291
|
+
case 'number':
|
|
292
|
+
return this.#formatNumberField(data[fieldName]);
|
|
293
|
+
case 'text':
|
|
294
|
+
case 'text-tiny':
|
|
295
|
+
case 'text-short':
|
|
296
|
+
case 'text-medium':
|
|
297
|
+
case 'text-long':
|
|
298
|
+
case 'text-giant':
|
|
299
|
+
return this.#formatTextField(data[fieldName], fieldInfo.fieldType);
|
|
300
|
+
default:
|
|
301
|
+
return String(data[fieldName]);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
catch (error) {
|
|
305
|
+
IDbError.handleError(error);
|
|
306
|
+
return '';
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
getInputDataSet(fieldName, data) {
|
|
310
|
+
const fieldInfo = this.dbCollections.parseCollectionFieldName(this.collection, fieldName);
|
|
311
|
+
const fieldType = fieldInfo?.fieldType ?? '';
|
|
312
|
+
const fieldArgs = fieldInfo?.fieldArgs?.join(' ') ?? '';
|
|
313
|
+
const indexName = this.dbCollections.getIndexName(this.collection);
|
|
314
|
+
return {
|
|
315
|
+
'data-collection': this.collection,
|
|
316
|
+
'data-collectionId': indexName && data?.[indexName] !== undefined ? String(data?.[indexName]) : '',
|
|
317
|
+
'data-fieldName': String(fieldName),
|
|
318
|
+
'data-fieldType': fieldType,
|
|
319
|
+
'data-fieldArgs': fieldArgs
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
iterateArrayField(fieldName, data) {
|
|
323
|
+
return this.dbCollections.iterateArrayField(this.collection, fieldName, data);
|
|
324
|
+
}
|
|
325
|
+
iterateObjectField(fieldName, data) {
|
|
326
|
+
return this.dbCollections.iterateObjectField(this.collection, fieldName, data);
|
|
327
|
+
}
|
|
328
|
+
#formatNumberField(value) {
|
|
329
|
+
// Implement number formatting logic here
|
|
330
|
+
return value.toString();
|
|
331
|
+
}
|
|
332
|
+
#formatTextField(value, type) {
|
|
333
|
+
const lengths = {
|
|
334
|
+
'text-tiny': 10,
|
|
335
|
+
'text-short': 20,
|
|
336
|
+
'text-medium': 30,
|
|
337
|
+
'text-long': 40,
|
|
338
|
+
'text-giant': 50
|
|
339
|
+
};
|
|
340
|
+
const maxLength = lengths[type] || value.length;
|
|
341
|
+
return value.substring(0, maxLength);
|
|
342
|
+
}
|
|
343
|
+
#checkAccess() {
|
|
344
|
+
// Implement access check logic here
|
|
345
|
+
return true;
|
|
346
|
+
}
|
|
347
|
+
#checkError(condition, message, code) {
|
|
348
|
+
if (condition) {
|
|
349
|
+
IDbError.throwError(message, code);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
export class IDbCollectionFieldValues {
|
|
354
|
+
#collection;
|
|
355
|
+
#collectionValues;
|
|
356
|
+
#data;
|
|
357
|
+
constructor(collection, data) {
|
|
358
|
+
this.#collection = collection;
|
|
359
|
+
this.#collectionValues = new IDbCollectionValues(collection);
|
|
360
|
+
this.#data = data;
|
|
361
|
+
}
|
|
362
|
+
format(fieldName) {
|
|
363
|
+
const fieldInfo = this.#collectionValues.dbCollections.parseCollectionFieldName(this.#collection, fieldName);
|
|
364
|
+
if (fieldInfo?.is === 'array') {
|
|
365
|
+
return this.iterateArray(String(fieldName), this.#data);
|
|
366
|
+
}
|
|
367
|
+
if (fieldInfo?.is === 'object') {
|
|
368
|
+
return this.iterateObject(String(fieldName), this.#data);
|
|
369
|
+
}
|
|
370
|
+
return this.#collectionValues.format(fieldName, this.#data);
|
|
371
|
+
}
|
|
372
|
+
getInputDataSet(fieldName) {
|
|
373
|
+
return this.#collectionValues.getInputDataSet(String(fieldName), this.#data);
|
|
374
|
+
}
|
|
375
|
+
// renamed from parseCollectionFieldName
|
|
376
|
+
getForge(fieldName) {
|
|
377
|
+
return this.#collectionValues.dbCollections.parseCollectionFieldName(this.#collection, String(fieldName));
|
|
378
|
+
}
|
|
379
|
+
iterateArray(fieldName, data) {
|
|
380
|
+
return this.#collectionValues.iterateArrayField(fieldName, data);
|
|
381
|
+
}
|
|
382
|
+
iterateObject(fieldName, data) {
|
|
383
|
+
return this.#collectionValues.iterateObjectField(fieldName, data);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
/*
|
|
387
|
+
path: D:\boulot\python\wollama\src\lib\db\dbFields.ts
|
|
388
|
+
forge values for a collection field and $data
|
|
389
|
+
*/
|
|
390
|
+
export class IDbCollectionFieldForge {
|
|
391
|
+
#collection;
|
|
392
|
+
#collectionValues;
|
|
393
|
+
#fieldName;
|
|
394
|
+
#data;
|
|
395
|
+
#forge;
|
|
396
|
+
constructor(collection, fieldName, data) {
|
|
397
|
+
this.#collection = collection;
|
|
398
|
+
this.#collectionValues = new IDbCollectionValues(collection);
|
|
399
|
+
this.#fieldName = String(fieldName);
|
|
400
|
+
this.#data = data;
|
|
401
|
+
}
|
|
402
|
+
get format() {
|
|
403
|
+
return this.#collectionValues.format(String(this.#fieldName), this.#data);
|
|
404
|
+
}
|
|
405
|
+
get inputDataSet() {
|
|
406
|
+
return this.#collectionValues.getInputDataSet(String(this.#fieldName), this.#data);
|
|
407
|
+
}
|
|
408
|
+
// renamed from parseCollectionFieldName
|
|
409
|
+
get forge() {
|
|
410
|
+
return this.#collectionValues.dbCollections.parseCollectionFieldName(this.#collection, String(this.#fieldName));
|
|
411
|
+
}
|
|
412
|
+
get fieldArgs() {
|
|
413
|
+
return this.forge?.fieldArgs;
|
|
414
|
+
}
|
|
415
|
+
get fieldType() {
|
|
416
|
+
return this.forge?.fieldType;
|
|
417
|
+
}
|
|
418
|
+
/**
|
|
419
|
+
* will return text.inputBase for ['url', 'email', 'number', 'date', 'time', 'datetime', 'phone', 'password']
|
|
420
|
+
*/
|
|
421
|
+
get htmlInputType() {
|
|
422
|
+
let variant = this?.fieldType?.split('text-')?.[1] ?? this.fieldType;
|
|
423
|
+
if (variant === 'area')
|
|
424
|
+
return variant;
|
|
425
|
+
if (this.forge?.fieldType?.startsWith('text-'))
|
|
426
|
+
return 'text';
|
|
427
|
+
if (['url', 'email', 'number', 'date', 'time', 'datetime', 'phone', 'password'].includes(this.forge?.fieldType ?? '')) {
|
|
428
|
+
return this.forge?.fieldType?.trim?.() ?? 'text';
|
|
429
|
+
}
|
|
430
|
+
return 'text';
|
|
431
|
+
}
|
|
432
|
+
get rawData() {
|
|
433
|
+
return this.#data;
|
|
434
|
+
}
|
|
435
|
+
iterateArray(fieldName, data) {
|
|
436
|
+
return this.#collectionValues.iterateArrayField(fieldName, data);
|
|
437
|
+
}
|
|
438
|
+
iterateObject(fieldName, data) {
|
|
439
|
+
return this.#collectionValues.iterateObjectField(fieldName, data);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
class IDbValidationError extends Error {
|
|
443
|
+
field;
|
|
444
|
+
code;
|
|
445
|
+
constructor(field, code, message) {
|
|
446
|
+
super(message);
|
|
447
|
+
this.field = field;
|
|
448
|
+
this.code = code;
|
|
449
|
+
this.name = 'IDbValidationError';
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
export class IDbFormValidate {
|
|
453
|
+
collection;
|
|
454
|
+
dbFields;
|
|
455
|
+
constructor(collection) {
|
|
456
|
+
this.collection = collection;
|
|
457
|
+
this.dbFields = new IDbCollections();
|
|
458
|
+
}
|
|
459
|
+
validateField(fieldName, value) {
|
|
460
|
+
try {
|
|
461
|
+
const fieldInfo = this.dbFields.parseCollectionFieldName(this.collection, fieldName);
|
|
462
|
+
if (!fieldInfo) {
|
|
463
|
+
return { isValid: false, error: `Field ${String(fieldName)} not found in collection` };
|
|
464
|
+
}
|
|
465
|
+
// Vérification du type
|
|
466
|
+
if (!this.#validateType(value, fieldInfo.fieldType)) {
|
|
467
|
+
return this.#returnError(fieldName, fieldInfo.fieldType);
|
|
468
|
+
}
|
|
469
|
+
// Vérification des arguments du champ (required, etc.)
|
|
470
|
+
if (fieldInfo.fieldArgs) {
|
|
471
|
+
for (const arg of fieldInfo.fieldArgs) {
|
|
472
|
+
if (arg === 'required' && (value === undefined || value === null || value === '')) {
|
|
473
|
+
return this.#returnError(fieldName, 'required');
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
// Validations spécifiques selon le type de champ
|
|
478
|
+
switch (fieldInfo.fieldType) {
|
|
479
|
+
case enumPrimitive.email:
|
|
480
|
+
if (!this.validateEmail(value)) {
|
|
481
|
+
return this.#returnError(fieldName, fieldInfo.fieldType);
|
|
482
|
+
}
|
|
483
|
+
break;
|
|
484
|
+
case enumPrimitive.url:
|
|
485
|
+
if (!this.validateUrl(value)) {
|
|
486
|
+
return this.#returnError(fieldName, fieldInfo.fieldType);
|
|
487
|
+
}
|
|
488
|
+
break;
|
|
489
|
+
case enumPrimitive.phone:
|
|
490
|
+
if (!this.validatePhone(value)) {
|
|
491
|
+
return this.#returnError(fieldName, fieldInfo.fieldType);
|
|
492
|
+
}
|
|
493
|
+
break;
|
|
494
|
+
case enumPrimitive.date:
|
|
495
|
+
case enumPrimitive.datetime:
|
|
496
|
+
case enumPrimitive.time:
|
|
497
|
+
if (!this.validateDateTime(value, fieldInfo.fieldType)) {
|
|
498
|
+
return this.#returnError(fieldName, fieldInfo.fieldType);
|
|
499
|
+
}
|
|
500
|
+
break;
|
|
501
|
+
// Ajoutez d'autres cas spécifiques ici
|
|
502
|
+
}
|
|
503
|
+
return { isValid: true };
|
|
504
|
+
}
|
|
505
|
+
catch (error) {
|
|
506
|
+
if (error instanceof IDbValidationError) {
|
|
507
|
+
return { isValid: false, error: error.message };
|
|
508
|
+
}
|
|
509
|
+
throw error;
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
validateFieldValue(fieldName, value) {
|
|
513
|
+
try {
|
|
514
|
+
this.validateField(fieldName, value);
|
|
515
|
+
return true;
|
|
516
|
+
}
|
|
517
|
+
catch {
|
|
518
|
+
return false;
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
validateForm(formData, options = {}) {
|
|
522
|
+
const errors = {};
|
|
523
|
+
const invalidFields = [];
|
|
524
|
+
let isValid = true;
|
|
525
|
+
const fields = this.dbFields.getCollectionTemplateFields(this.collection);
|
|
526
|
+
if (!fields) {
|
|
527
|
+
return {
|
|
528
|
+
isValid: false,
|
|
529
|
+
errors: { general: 'Collection template not found' },
|
|
530
|
+
invalidFields: ['general']
|
|
531
|
+
};
|
|
532
|
+
}
|
|
533
|
+
for (const [fieldName, fieldRule] of Object.entries(fields)) {
|
|
534
|
+
// Ignorer les champs spécifiés dans options.ignoreFields
|
|
535
|
+
if (options.ignoreFields && options.ignoreFields.includes(fieldName)) {
|
|
536
|
+
continue;
|
|
537
|
+
}
|
|
538
|
+
const result = this.validateField(fieldName, formData[fieldName]);
|
|
539
|
+
if (!result.isValid) {
|
|
540
|
+
errors[fieldName] = result.error || 'Invalid field';
|
|
541
|
+
invalidFields.push(fieldName);
|
|
542
|
+
isValid = false;
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
return { isValid, errors, invalidFields };
|
|
546
|
+
}
|
|
547
|
+
#validateType(value, type) {
|
|
548
|
+
switch (type) {
|
|
549
|
+
case enumPrimitive.number:
|
|
550
|
+
return typeof value === 'number' && !isNaN(value);
|
|
551
|
+
case enumPrimitive.boolean:
|
|
552
|
+
return typeof value === 'boolean';
|
|
553
|
+
case enumPrimitive.text:
|
|
554
|
+
case enumPrimitive.email:
|
|
555
|
+
case enumPrimitive.url:
|
|
556
|
+
case enumPrimitive.phone:
|
|
557
|
+
case enumPrimitive.password:
|
|
558
|
+
return typeof value === 'string';
|
|
559
|
+
case enumPrimitive.date:
|
|
560
|
+
case enumPrimitive.datetime:
|
|
561
|
+
case enumPrimitive.time:
|
|
562
|
+
return value instanceof Date || typeof value === 'string';
|
|
563
|
+
case enumPrimitive.any:
|
|
564
|
+
return true;
|
|
565
|
+
default:
|
|
566
|
+
return true; // Pour les types non gérés, on considère que c'est valide
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
#returnError(fieldName, enumCode) {
|
|
570
|
+
throw new IDbValidationError(String(fieldName), enumCode ?? 'unknown', `Invalid format for field ${String(fieldName)}. Cause "${enumCode}" `);
|
|
571
|
+
}
|
|
572
|
+
validateEmail(email) {
|
|
573
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
574
|
+
return emailRegex.test(email);
|
|
575
|
+
}
|
|
576
|
+
validateUrl(url) {
|
|
577
|
+
try {
|
|
578
|
+
new URL(url);
|
|
579
|
+
return true;
|
|
580
|
+
}
|
|
581
|
+
catch {
|
|
582
|
+
return false;
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
validatePhone(phone) {
|
|
586
|
+
// Ceci est un exemple simple. Vous pouvez ajuster selon vos besoins spécifiques
|
|
587
|
+
const phoneRegex = /^\+?[\d\s-]{10,}$/;
|
|
588
|
+
return phoneRegex.test(phone);
|
|
589
|
+
}
|
|
590
|
+
validateDateTime(value, type) {
|
|
591
|
+
const date = value instanceof Date ? value : new Date(value);
|
|
592
|
+
if (isNaN(date.getTime()))
|
|
593
|
+
return false;
|
|
594
|
+
switch (type) {
|
|
595
|
+
case enumPrimitive.date:
|
|
596
|
+
return true; // La conversion en Date a déjà validé le format
|
|
597
|
+
case enumPrimitive.time:
|
|
598
|
+
// Vérifiez si la chaîne contient uniquement l'heure
|
|
599
|
+
return /^([01]\d|2[0-3]):([0-5]\d)(:([0-5]\d))?$/.test(value);
|
|
600
|
+
case enumPrimitive.datetime:
|
|
601
|
+
return true; // La conversion en Date a déjà validé le format
|
|
602
|
+
default:
|
|
603
|
+
return false;
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
}
|