@medyll/idae-machine 0.106.0 โ†’ 0.108.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 CHANGED
@@ -159,23 +159,37 @@ fields: {
159
159
  }
160
160
  ```
161
161
 
162
- ## ๐Ÿ“ Development Status
163
162
 
164
- โš ๏ธ **Early Development Phase**
163
+ ## ๐Ÿ›ก๏ธ Robustness & Test Coverage
165
164
 
166
- This package contains foundational code that is:
167
- - **Partially validated**: Core schema & field system works; form validation in progress
168
- - **Under active refinement**: API may change as patterns solidify
169
- - **Proof of concept**: Not recommended for production until v1.0 release
165
+ All core logic in `src/lib/db/dbFields.ts` is now fully schema-driven and covered by comprehensive unit tests (see `src/lib/db/*.spec.ts`).
166
+
167
+ - **Field parsing**: Handles all types (primitive, array, object, fk) and modifiers (required, readonly, private) with robust string DSL parsing.
168
+ - **Foreign key support**: Correctly parses and exposes fk and reverse-fk relations, with type-safe metadata.
169
+ - **Test-driven**: All exported classes are covered by robust Vitest suites, including edge cases and complex schemas.
170
+ - **Svelte 5 compliance**: All UI code and event handling strictly follow Svelte 5 idioms (see `AGENTS.md`).
170
171
 
171
172
  ### Current Focus Areas
172
173
  - โœ… Schema declaration & type safety
173
174
  - โœ… Database integration with idae-idbql
174
175
  - โœ… Component exports & library structure
176
+ - โœ… Comprehensive test coverage (dbFields, CRUD, UI)
177
+ - โœ… Svelte 5 event and binding policy
175
178
  - ๐Ÿ”„ Form validation (in progress)
176
179
  - ๐Ÿ”„ Field rendering pipeline (needs refinement)
177
180
  - โณ End-to-end CRUD workflows
178
- - โณ Comprehensive test coverage
181
+
182
+ ## ๐Ÿงช Testing Policy
183
+
184
+ All logic in `dbFields.ts` and related modules is covered by unit tests:
185
+
186
+ - **Test schema**: All tests use a realistic, complex schema (see `testDbSchema.ts`).
187
+ - **Coverage**: Every method of every exported class is tested, including edge cases (array/object/fk/required/readonly).
188
+ - **Continuous validation**: All tests must pass before merge. See `CHANGELOG.md` for test and coverage history.
189
+
190
+ ## ๐Ÿฆ„ Svelte 5 Coding Policy
191
+
192
+ All UI code must strictly follow Svelte 5 syntax and conventions. See `AGENTS.md` for details and migration rules.
179
193
 
180
194
  ## ๐Ÿ”— Dependencies
181
195
 
@@ -38,54 +38,227 @@ export type IDbForge = {
38
38
  fieldArgs?: IDbForgeArgs | undefined;
39
39
  is: any;
40
40
  };
41
+ /**
42
+ * Central class for parsing, introspecting, and extracting metadata from the database schema.
43
+ * Provides methods to access collections, templates, fields, foreign keys, and type information.
44
+ * Used for dynamic UI generation, validation, and schema-driven logic.
45
+ */
41
46
  export declare class IDbCollections {
42
47
  #private;
48
+ /**
49
+ * The database model (schema) used for introspection.
50
+ */
43
51
  model: IdbqModel;
52
+ /**
53
+ * Create a new IDbCollections instance.
54
+ * @param model Optional custom model to use (default: schemeModel)
55
+ */
44
56
  constructor(model?: IdbqModel);
57
+ /**
58
+ * Parse all collections in the model and return their fields as IDbForge objects.
59
+ * @returns An object mapping collection names to their parsed fields.
60
+ */
45
61
  parseAllCollections(): Record<string, Record<string, IDbForge | undefined> | undefined>;
62
+ /**
63
+ * Parse all fields of a given collection.
64
+ * @param collection The collection name.
65
+ * @returns An object mapping field names to their IDbForge representation.
66
+ */
46
67
  parseRawCollection(collection: TplCollectionName): Record<string, IDbForge | undefined> | undefined;
68
+ /**
69
+ * Parse a single field of a collection and return its IDbForge metadata.
70
+ * @param collection The collection name.
71
+ * @param fieldName The field name.
72
+ * @returns The IDbForge object for the field, or throws if not found.
73
+ */
47
74
  parseCollectionFieldName(collection: TplCollectionName, fieldName: keyof TplFields): IDbForge | undefined;
75
+ /**
76
+ * Parse a field rule string and extract its type and arguments.
77
+ * @param fieldRule The field rule string.
78
+ * @returns Partial IDbForge info for the rule.
79
+ */
48
80
  parsFieldRule(fieldRule: IDbFieldRules): Partial<IDbForge> | undefined;
81
+ /**
82
+ * Internal helper to construct an IDbForge object from its components.
83
+ * @param params The IDbForge properties (collection, fieldName, fieldType, fieldRule, fieldArgs, is).
84
+ * @returns The constructed IDbForge object.
85
+ */
49
86
  private forge;
87
+ /**
88
+ * Get the collection object from the model.
89
+ * @param collection The collection name.
90
+ * @returns The collection object.
91
+ */
50
92
  getCollection(collection: TplCollectionName): CollectionModel;
93
+ /**
94
+ * Get the template object for a collection.
95
+ * @param collection The collection name.
96
+ * @returns The template object.
97
+ */
51
98
  getCollectionTemplate(collection: TplCollectionName): Tpl;
99
+ /**
100
+ * Get the foreign keys (fks) object for a collection.
101
+ * @param collection The collection name.
102
+ * @returns The fks object.
103
+ */
52
104
  getCollectionTemplateFks(collection: TplCollectionName): Tpl["fks"];
105
+ /**
106
+ * Get the index field name for a collection.
107
+ * @param collection The collection name.
108
+ * @returns The index field name.
109
+ */
53
110
  getIndexName(collection: string): string;
111
+ /**
112
+ * Get the fields object for a collection.
113
+ * @param collection The collection name.
114
+ * @returns The fields object.
115
+ */
54
116
  getCollectionTemplateFields(collection: TplCollectionName): TplFields;
117
+ /**
118
+ * Get the presentation string for a collection (used for display).
119
+ * @param collection The collection name.
120
+ * @returns The presentation string.
121
+ */
55
122
  getTemplatePresentation(collection: TplCollectionName): string;
123
+ /**
124
+ * Get the field rule for a foreign key field (e.g. 'collection.field').
125
+ * @param string The string in the form 'collection.field'.
126
+ * @returns The field rule string, or undefined.
127
+ */
56
128
  getFkFieldType(string: `${string}.${string}`): IDbFieldRules | undefined;
129
+ /**
130
+ * Get the fields object for a foreign key collection.
131
+ * @param string The string in the form 'collection.field'.
132
+ * @returns The fields object for the referenced collection.
133
+ */
57
134
  getFkTemplateFields(string: `${string}.${string}`): {
58
135
  [x: string]: import("@medyll/idae-idbql").TplFieldRules;
59
136
  };
137
+ /**
138
+ * Test if a field rule matches a given type (primitive, array, object, fk).
139
+ * @param what The type to test ('primitive', 'array', 'object', 'fk').
140
+ * @param fieldRule The field rule string.
141
+ * @returns Partial IDbForge info if match, else undefined.
142
+ */
60
143
  private testIs;
144
+ /**
145
+ * Extract type information for a field rule.
146
+ * @param what The type to extract ('primitive', 'array', 'object', 'fk').
147
+ * @param fieldRule The field rule string.
148
+ * @returns Partial IDbForge info.
149
+ */
61
150
  is(what: 'array' | 'object' | 'fk' | 'primitive', fieldRule: IDbFieldRules): Partial<IDbForge>;
151
+ /**
152
+ * Get the value of the index field for a given data object.
153
+ * @param collection The collection name.
154
+ * @param data The data object.
155
+ * @returns The value of the index field.
156
+ */
62
157
  indexValue(collection: TplCollectionName, data: Record<string, any>): any;
158
+ /**
159
+ * Extracts type, rule, and argument information from a field rule string.
160
+ * @param type The type to extract ('primitive', 'array', 'object', 'fk').
161
+ * @param fieldRule The field rule string.
162
+ * @returns Partial IDbForge info.
163
+ */
63
164
  extract(type: 'array' | 'object' | 'fk' | 'primitive', fieldRule: IDbFieldRules): Partial<IDbForge>;
165
+ /**
166
+ * Parse and return all foreign key collections referenced by a collection.
167
+ * @param collection The collection name.
168
+ * @returns An object mapping referenced collection names to their parsed fields.
169
+ */
64
170
  fks(collection: string): {
65
171
  [collection: string]: Tpl;
66
172
  };
173
+ /**
174
+ * Find all collections that reference the target collection via a foreign key.
175
+ * @param targetCollection The collection name to search for as a target.
176
+ * @returns An object mapping referencing collections to their fk configs.
177
+ */
67
178
  reverseFks(targetCollection: TplCollectionName): Record<string, any>;
179
+ /**
180
+ * Iterate over an array field and return an array of IDbForge objects for each element.
181
+ * @param collection The collection name.
182
+ * @param fieldName The field name.
183
+ * @param data The array data.
184
+ * @returns An array of IDbForge objects.
185
+ */
68
186
  iterateArrayField(collection: TplCollectionName, fieldName: keyof TplFields, data: any[]): IDbForge[];
187
+ /**
188
+ * Iterate over an object field and return an array of IDbForge objects for each property.
189
+ * @param collection The collection name.
190
+ * @param fieldName The field name.
191
+ * @param data The object data.
192
+ * @returns An array of IDbForge objects.
193
+ */
69
194
  iterateObjectField(collection: TplCollectionName, fieldName: keyof TplFields, data: Record<string, any>): IDbForge[];
70
195
  }
196
+ /**
197
+ * Utility class to display and format field values for a collection, based on the schema and provided data.
198
+ * Used for dynamic UI rendering, presentation, and extracting metadata for form generation.
199
+ * @template T The data type for the collection.
200
+ */
71
201
  export declare class IDbCollectionValues<T extends Record<string, any>> {
72
202
  #private;
203
+ /**
204
+ * The IDbCollections instance used for schema introspection.
205
+ */
73
206
  dbCollections: IDbCollections;
207
+ /**
208
+ * The collection name this instance operates on.
209
+ */
74
210
  private collection;
211
+ /**
212
+ * Create a new IDbCollectionValues instance for a given collection.
213
+ * @param collection The collection name.
214
+ */
75
215
  constructor(collection: TplCollectionName);
76
216
  presentation(data: Record<string, any>): string;
217
+ /**
218
+ * Get the value of the index field for a data object.
219
+ * @param data The data object.
220
+ * @returns The value of the index field, or null if not found.
221
+ */
77
222
  indexValue(data: Record<string, any>): any | null;
223
+ /**
224
+ * Format a field value for display, using the field type and schema.
225
+ * @param fieldName The field name.
226
+ * @param data The data object.
227
+ * @returns The formatted value as a string.
228
+ */
78
229
  format(fieldName: keyof T, data: T): string;
230
+ /**
231
+ * Get a set of data-* attributes for a field, for use in form generation or UI.
232
+ * @param fieldName The field name.
233
+ * @param data The data object.
234
+ * @returns An object with data-* attributes for the field.
235
+ */
79
236
  getInputDataSet(fieldName: string, data: T): Record<`data-${'collection' | 'collectionId' | 'fieldName' | 'fieldType' | 'fieldArgs'}`, string>;
237
+ /**
238
+ * Iterate over an array field and return an array of IDbForge objects for each element.
239
+ * @param fieldName The field name.
240
+ * @param data The array data.
241
+ * @returns An array of IDbForge objects.
242
+ */
80
243
  iterateArrayField(fieldName: keyof TplFields, data: any[]): IDbForge[];
244
+ /**
245
+ * Iterate over an object field and return an array of IDbForge objects for each property.
246
+ * @param fieldName The field name.
247
+ * @param data The object data.
248
+ * @returns An array of IDbForge objects.
249
+ */
81
250
  iterateObjectField(fieldName: keyof TplFields, data: Record<string, any>): IDbForge[];
82
251
  }
83
252
  export declare class IDbCollectionFieldValues<T extends Record<string, any>> {
84
253
  #private;
254
+ /**
255
+ * Returns the IDbForge metadata for a given field name.
256
+ * @param fieldName The field name to introspect.
257
+ */
258
+ getForge(fieldName: keyof T): IDbForge | undefined;
85
259
  constructor(collection: TplCollectionName, data: T);
86
260
  format(fieldName: keyof T): string | string[];
87
261
  getInputDataSet(fieldName: keyof T): Record<"data-collection" | "data-fieldName" | "data-fieldType" | "data-fieldArgs" | "data-collectionId", string>;
88
- getForge(fieldName: keyof T): IDbForge | undefined;
89
262
  iterateArray(fieldName: string, data: any[]): IDbForge[];
90
263
  iterateObject(fieldName: string, data: Record<string, any>): IDbForge[];
91
264
  }
@@ -114,6 +287,12 @@ export declare class IDbFormValidate {
114
287
  isValid: boolean;
115
288
  error?: string;
116
289
  };
290
+ /**
291
+ * Validate a single field value for a collection.
292
+ * @param fieldName The field name.
293
+ * @param value The value to validate.
294
+ * @returns True if valid, false otherwise.
295
+ */
117
296
  validateFieldValue(fieldName: keyof TplFields, value: any): boolean;
118
297
  validateForm(formData: Record<string, any>, options?: {
119
298
  ignoreFields?: string[] | undefined;
@@ -46,12 +46,27 @@ class IDbError extends Error {
46
46
  }
47
47
  }
48
48
  }
49
- // renammed from IDbFields to IDbCollections
49
+ /**
50
+ * Central class for parsing, introspecting, and extracting metadata from the database schema.
51
+ * Provides methods to access collections, templates, fields, foreign keys, and type information.
52
+ * Used for dynamic UI generation, validation, and schema-driven logic.
53
+ */
50
54
  export class IDbCollections {
55
+ /**
56
+ * The database model (schema) used for introspection.
57
+ */
51
58
  model = schemeModel;
59
+ /**
60
+ * Create a new IDbCollections instance.
61
+ * @param model Optional custom model to use (default: schemeModel)
62
+ */
52
63
  constructor(model) {
53
- this.model = schemeModel; //model ?? this.model;
64
+ this.model = model ?? schemeModel;
54
65
  }
66
+ /**
67
+ * Parse all collections in the model and return their fields as IDbForge objects.
68
+ * @returns An object mapping collection names to their parsed fields.
69
+ */
55
70
  parseAllCollections() {
56
71
  let out = {};
57
72
  Object.keys(this.model).forEach((collection) => {
@@ -59,6 +74,11 @@ export class IDbCollections {
59
74
  });
60
75
  return out;
61
76
  }
77
+ /**
78
+ * Parse all fields of a given collection.
79
+ * @param collection The collection name.
80
+ * @returns An object mapping field names to their IDbForge representation.
81
+ */
62
82
  parseRawCollection(collection) {
63
83
  const fields = this.getCollectionTemplateFields(collection);
64
84
  if (!fields)
@@ -72,18 +92,30 @@ export class IDbCollections {
72
92
  });
73
93
  return out;
74
94
  }
95
+ /**
96
+ * Parse a single field of a collection and return its IDbForge metadata.
97
+ * @param collection The collection name.
98
+ * @param fieldName The field name.
99
+ * @returns The IDbForge object for the field, or throws if not found.
100
+ */
75
101
  parseCollectionFieldName(collection, fieldName) {
76
102
  const field = this.#getTemplateFieldRule(collection, fieldName);
77
103
  if (!field) {
78
104
  IDbError.throwError(`Field ${fieldName} not found in collection ${collection}`, 'FIELD_NOT_FOUND');
79
105
  return undefined;
80
106
  }
81
- const fieldType = this.testIs('primitive', field) ??
82
- this.testIs('array', field) ??
83
- this.testIs('object', field) ??
84
- this.testIs('fk', field);
107
+ const array = this.testIs('array', field);
108
+ const object = this.testIs('object', field);
109
+ const fk = this.testIs('fk', field);
110
+ const primitive = this.testIs('primitive', field);
111
+ const fieldType = array ?? object ?? fk ?? primitive;
85
112
  return this.forge({ collection, fieldName, ...fieldType });
86
113
  }
114
+ /**
115
+ * Parse a field rule string and extract its type and arguments.
116
+ * @param fieldRule The field rule string.
117
+ * @returns Partial IDbForge info for the rule.
118
+ */
87
119
  parsFieldRule(fieldRule) {
88
120
  if (!fieldRule)
89
121
  return;
@@ -93,6 +125,11 @@ export class IDbCollections {
93
125
  this.testIs('fk', fieldRule);
94
126
  return fieldType;
95
127
  }
128
+ /**
129
+ * Internal helper to construct an IDbForge object from its components.
130
+ * @param params The IDbForge properties (collection, fieldName, fieldType, fieldRule, fieldArgs, is).
131
+ * @returns The constructed IDbForge object.
132
+ */
96
133
  forge({ collection, fieldName, fieldType, fieldRule, fieldArgs, is }) {
97
134
  return {
98
135
  collection,
@@ -106,36 +143,82 @@ export class IDbCollections {
106
143
  #getModel() {
107
144
  return this.model;
108
145
  }
146
+ /**
147
+ * Get the collection object from the model.
148
+ * @param collection The collection name.
149
+ * @returns The collection object.
150
+ */
109
151
  getCollection(collection) {
110
152
  return this.#getModel()[String(collection)];
111
153
  }
154
+ /**
155
+ * Get the template object for a collection.
156
+ * @param collection The collection name.
157
+ * @returns The template object.
158
+ */
112
159
  getCollectionTemplate(collection) {
113
160
  return this.getCollection(collection)['template'];
114
161
  }
162
+ /**
163
+ * Get the foreign keys (fks) object for a collection.
164
+ * @param collection The collection name.
165
+ * @returns The fks object.
166
+ */
115
167
  getCollectionTemplateFks(collection) {
116
168
  return this.getCollection(collection)['template']?.fks;
117
169
  }
170
+ /**
171
+ * Get the index field name for a collection.
172
+ * @param collection The collection name.
173
+ * @returns The index field name.
174
+ */
118
175
  getIndexName(collection) {
119
176
  return this.getCollection(collection)?.template?.index;
120
177
  }
178
+ /**
179
+ * Get the fields object for a collection.
180
+ * @param collection The collection name.
181
+ * @returns The fields object.
182
+ */
121
183
  getCollectionTemplateFields(collection) {
122
184
  return this.getCollectionTemplate(collection)?.fields;
123
185
  }
186
+ /**
187
+ * Get the presentation string for a collection (used for display).
188
+ * @param collection The collection name.
189
+ * @returns The presentation string.
190
+ */
124
191
  getTemplatePresentation(collection) {
125
192
  return this.getCollectionTemplate(collection)?.presentation;
126
193
  }
127
194
  #getTemplateFieldRule(collection, fieldName) {
128
195
  return this.getCollectionTemplateFields(collection)?.[String(fieldName)];
129
196
  }
197
+ /**
198
+ * Get the field rule for a foreign key field (e.g. 'collection.field').
199
+ * @param string The string in the form 'collection.field'.
200
+ * @returns The field rule string, or undefined.
201
+ */
130
202
  getFkFieldType(string) {
131
203
  const [collection, field] = string.split('.');
132
204
  let template = this.#getTemplateFieldRule(collection, field);
133
205
  return template;
134
206
  }
207
+ /**
208
+ * Get the fields object for a foreign key collection.
209
+ * @param string The string in the form 'collection.field'.
210
+ * @returns The fields object for the referenced collection.
211
+ */
135
212
  getFkTemplateFields(string) {
136
213
  const [collection, field] = string.split('.');
137
214
  return this.getCollection(collection).template?.fields;
138
215
  }
216
+ /**
217
+ * Test if a field rule matches a given type (primitive, array, object, fk).
218
+ * @param what The type to test ('primitive', 'array', 'object', 'fk').
219
+ * @param fieldRule The field rule string.
220
+ * @returns Partial IDbForge info if match, else undefined.
221
+ */
139
222
  testIs(what, fieldRule) {
140
223
  const typeMappings = {
141
224
  fk: 'fk-',
@@ -144,18 +227,45 @@ export class IDbCollections {
144
227
  primitive: ''
145
228
  };
146
229
  const prefix = typeMappings[what];
230
+ if (what === 'primitive') {
231
+ // Un type primitif ne doit pas commencer par un prรฉfixe array/object/fk
232
+ if (!fieldRule.startsWith('array-of-') &&
233
+ !fieldRule.startsWith('object-') &&
234
+ !fieldRule.startsWith('fk-')) {
235
+ return this.is(what, fieldRule);
236
+ }
237
+ return undefined;
238
+ }
147
239
  if (fieldRule.startsWith(prefix)) {
148
240
  return this.is(what, fieldRule);
149
241
  }
150
242
  return undefined;
151
243
  }
244
+ /**
245
+ * Extract type information for a field rule.
246
+ * @param what The type to extract ('primitive', 'array', 'object', 'fk').
247
+ * @param fieldRule The field rule string.
248
+ * @returns Partial IDbForge info.
249
+ */
152
250
  is(what, fieldRule) {
153
251
  return this.extract(what, fieldRule);
154
252
  }
253
+ /**
254
+ * Get the value of the index field for a given data object.
255
+ * @param collection The collection name.
256
+ * @param data The data object.
257
+ * @returns The value of the index field.
258
+ */
155
259
  indexValue(collection, data) {
156
260
  let presentation = this.getIndexName(collection);
157
261
  return data[presentation];
158
262
  }
263
+ /**
264
+ * Extracts type, rule, and argument information from a field rule string.
265
+ * @param type The type to extract ('primitive', 'array', 'object', 'fk').
266
+ * @param fieldRule The field rule string.
267
+ * @returns Partial IDbForge info.
268
+ */
159
269
  extract(type, fieldRule) {
160
270
  // fieldType
161
271
  function extractAfter(pattern, source) {
@@ -186,7 +296,8 @@ export class IDbCollections {
186
296
  is = is ?? fieldType;
187
297
  break;
188
298
  case 'fk':
189
- fieldType = this.getFkFieldType(extractAfter('fk-', fieldRule));
299
+ // Pour les fk, fieldType doit rester la string d'origine (ex: 'fk-agentPrompt.id')
300
+ fieldType = 'fk-' + extractAfter('fk-', fieldRule);
190
301
  is = extractedArgs?.piece;
191
302
  break;
192
303
  case 'primitive':
@@ -196,6 +307,11 @@ export class IDbCollections {
196
307
  }
197
308
  return { fieldType, fieldRule, fieldArgs, is: type };
198
309
  }
310
+ /**
311
+ * Parse and return all foreign key collections referenced by a collection.
312
+ * @param collection The collection name.
313
+ * @returns An object mapping referenced collection names to their parsed fields.
314
+ */
199
315
  fks(collection) {
200
316
  let fks = this.getCollectionTemplateFks(collection);
201
317
  let out = {};
@@ -207,6 +323,11 @@ export class IDbCollections {
207
323
  }
208
324
  return out;
209
325
  }
326
+ /**
327
+ * Find all collections that reference the target collection via a foreign key.
328
+ * @param targetCollection The collection name to search for as a target.
329
+ * @returns An object mapping referencing collections to their fk configs.
330
+ */
210
331
  reverseFks(targetCollection) {
211
332
  const result = {};
212
333
  Object.entries(this.#getModel()).forEach(([collectionName, collectionModel]) => {
@@ -225,27 +346,61 @@ export class IDbCollections {
225
346
  return result;
226
347
  }
227
348
  // iterate base
349
+ /**
350
+ * Iterate over an array field and return an array of IDbForge objects for each element.
351
+ * @param collection The collection name.
352
+ * @param fieldName The field name.
353
+ * @param data The array data.
354
+ * @returns An array of IDbForge objects.
355
+ */
228
356
  iterateArrayField(collection, fieldName, data) {
229
357
  const fieldInfo = this.parseCollectionFieldName(collection, fieldName);
230
358
  if (fieldInfo?.is !== 'array' || !Array.isArray(data)) {
231
359
  return [];
232
360
  }
233
- return data.map(() => this.parseCollectionFieldName(collection, fieldName));
361
+ // Retourne un tableau d'objets IDbForge gรฉnรฉriques pour chaque รฉlรฉment
362
+ return data.map((_, idx) => ({
363
+ ...fieldInfo,
364
+ fieldName: `${String(fieldName)}[${idx}]`,
365
+ }));
234
366
  }
367
+ /**
368
+ * Iterate over an object field and return an array of IDbForge objects for each property.
369
+ * @param collection The collection name.
370
+ * @param fieldName The field name.
371
+ * @param data The object data.
372
+ * @returns An array of IDbForge objects.
373
+ */
235
374
  iterateObjectField(collection, fieldName, data) {
236
375
  const fieldInfo = this.parseCollectionFieldName(collection, fieldName);
237
- if (fieldInfo?.is !== 'object' || typeof data !== 'object') {
376
+ if (fieldInfo?.is !== 'object' || typeof data !== 'object' || data === null) {
238
377
  return [];
239
378
  }
240
- return Object.keys(data).map((key) => this.parseCollectionFieldName(collection, key));
379
+ // Retourne un tableau d'objets IDbForge gรฉnรฉriques pour chaque clรฉ
380
+ return Object.keys(data).map((key) => ({
381
+ ...fieldInfo,
382
+ fieldName: `${String(fieldName)}.${key}`,
383
+ }));
241
384
  }
242
385
  }
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
386
+ /**
387
+ * Utility class to display and format field values for a collection, based on the schema and provided data.
388
+ * Used for dynamic UI rendering, presentation, and extracting metadata for form generation.
389
+ * @template T The data type for the collection.
390
+ */
246
391
  export class IDbCollectionValues {
392
+ /**
393
+ * The IDbCollections instance used for schema introspection.
394
+ */
247
395
  dbCollections;
396
+ /**
397
+ * The collection name this instance operates on.
398
+ */
248
399
  collection;
400
+ /**
401
+ * Create a new IDbCollectionValues instance for a given collection.
402
+ * @param collection The collection name.
403
+ */
249
404
  constructor(collection) {
250
405
  this.collection = collection;
251
406
  this.dbCollections = new IDbCollections();
@@ -268,6 +423,11 @@ export class IDbCollectionValues {
268
423
  return '';
269
424
  }
270
425
  }
426
+ /**
427
+ * Get the value of the index field for a data object.
428
+ * @param data The data object.
429
+ * @returns The value of the index field, or null if not found.
430
+ */
271
431
  indexValue(data) {
272
432
  try {
273
433
  this.#checkError(!this.#checkAccess(), 'Access denied', 'ACCESS_DENIED');
@@ -281,6 +441,12 @@ export class IDbCollectionValues {
281
441
  return null;
282
442
  }
283
443
  }
444
+ /**
445
+ * Format a field value for display, using the field type and schema.
446
+ * @param fieldName The field name.
447
+ * @param data The data object.
448
+ * @returns The formatted value as a string.
449
+ */
284
450
  format(fieldName, data) {
285
451
  try {
286
452
  this.#checkError(!this.#checkAccess(), 'Access denied', 'ACCESS_DENIED');
@@ -306,6 +472,12 @@ export class IDbCollectionValues {
306
472
  return '';
307
473
  }
308
474
  }
475
+ /**
476
+ * Get a set of data-* attributes for a field, for use in form generation or UI.
477
+ * @param fieldName The field name.
478
+ * @param data The data object.
479
+ * @returns An object with data-* attributes for the field.
480
+ */
309
481
  getInputDataSet(fieldName, data) {
310
482
  const fieldInfo = this.dbCollections.parseCollectionFieldName(this.collection, fieldName);
311
483
  const fieldType = fieldInfo?.fieldType ?? '';
@@ -319,16 +491,39 @@ export class IDbCollectionValues {
319
491
  'data-fieldArgs': fieldArgs
320
492
  };
321
493
  }
494
+ /**
495
+ * Iterate over an array field and return an array of IDbForge objects for each element.
496
+ * @param fieldName The field name.
497
+ * @param data The array data.
498
+ * @returns An array of IDbForge objects.
499
+ */
322
500
  iterateArrayField(fieldName, data) {
323
501
  return this.dbCollections.iterateArrayField(this.collection, fieldName, data);
324
502
  }
503
+ /**
504
+ * Iterate over an object field and return an array of IDbForge objects for each property.
505
+ * @param fieldName The field name.
506
+ * @param data The object data.
507
+ * @returns An array of IDbForge objects.
508
+ */
325
509
  iterateObjectField(fieldName, data) {
326
510
  return this.dbCollections.iterateObjectField(this.collection, fieldName, data);
327
511
  }
512
+ /**
513
+ * Internal: Format a number field for display.
514
+ * @param value The number value.
515
+ * @returns The formatted string.
516
+ */
328
517
  #formatNumberField(value) {
329
518
  // Implement number formatting logic here
330
519
  return value.toString();
331
520
  }
521
+ /**
522
+ * Internal: Format a text field for display, with length limits by type.
523
+ * @param value The string value.
524
+ * @param type The text type (e.g. 'text-short').
525
+ * @returns The formatted string.
526
+ */
332
527
  #formatTextField(value, type) {
333
528
  const lengths = {
334
529
  'text-tiny': 10,
@@ -340,10 +535,20 @@ export class IDbCollectionValues {
340
535
  const maxLength = lengths[type] || value.length;
341
536
  return value.substring(0, maxLength);
342
537
  }
538
+ /**
539
+ * Internal: Check if access is allowed (override for custom logic).
540
+ * @returns True if access is allowed.
541
+ */
343
542
  #checkAccess() {
344
543
  // Implement access check logic here
345
544
  return true;
346
545
  }
546
+ /**
547
+ * Internal: Throw an error if a condition is met.
548
+ * @param condition The condition to check.
549
+ * @param message The error message.
550
+ * @param code The error code.
551
+ */
347
552
  #checkError(condition, message, code) {
348
553
  if (condition) {
349
554
  IDbError.throwError(message, code);
@@ -354,6 +559,13 @@ export class IDbCollectionFieldValues {
354
559
  #collection;
355
560
  #collectionValues;
356
561
  #data;
562
+ /**
563
+ * Returns the IDbForge metadata for a given field name.
564
+ * @param fieldName The field name to introspect.
565
+ */
566
+ getForge(fieldName) {
567
+ return this.#collectionValues.dbCollections.parseCollectionFieldName(this.#collection, String(fieldName));
568
+ }
357
569
  constructor(collection, data) {
358
570
  this.#collection = collection;
359
571
  this.#collectionValues = new IDbCollectionValues(collection);
@@ -373,9 +585,9 @@ export class IDbCollectionFieldValues {
373
585
  return this.#collectionValues.getInputDataSet(String(fieldName), this.#data);
374
586
  }
375
587
  // renamed from parseCollectionFieldName
376
- getForge(fieldName) {
377
- return this.#collectionValues.dbCollections.parseCollectionFieldName(this.#collection, String(fieldName));
378
- }
588
+ // get forge(): IDbForge | undefined {
589
+ // return undefined; // Pas de #fieldName dans cette classe, getter non pertinent
590
+ // }
379
591
  iterateArray(fieldName, data) {
380
592
  return this.#collectionValues.iterateArrayField(fieldName, data);
381
593
  }
@@ -509,14 +721,15 @@ export class IDbFormValidate {
509
721
  throw error;
510
722
  }
511
723
  }
724
+ /**
725
+ * Validate a single field value for a collection.
726
+ * @param fieldName The field name.
727
+ * @param value The value to validate.
728
+ * @returns True if valid, false otherwise.
729
+ */
512
730
  validateFieldValue(fieldName, value) {
513
- try {
514
- this.validateField(fieldName, value);
515
- return true;
516
- }
517
- catch {
518
- return false;
519
- }
731
+ const result = this.validateField(fieldName, value);
732
+ return !!result.isValid;
520
733
  }
521
734
  validateForm(formData, options = {}) {
522
735
  const errors = {};
@@ -604,3 +817,4 @@ export class IDbFormValidate {
604
817
  }
605
818
  }
606
819
  }
820
+ // (fin de fichier)
@@ -0,0 +1,56 @@
1
+ import type { DBAgent, DbAgentPrompt } from '$types/db';
2
+ import { type IdbqModel } from '@medyll/idae-idbql';
3
+ import type { DbDataModelTs } from './dataModel.js';
4
+ export declare const schemeModelTestDb: {
5
+ agent: {
6
+ keyPath: string;
7
+ model: DBAgent;
8
+ ts: DBAgent;
9
+ template: {
10
+ index: string;
11
+ presentation: string;
12
+ fields: {
13
+ id: string;
14
+ name: string;
15
+ code: string;
16
+ model: string;
17
+ prompt: string;
18
+ created_at: string;
19
+ ia_lock: string;
20
+ agentPromptId: string;
21
+ tags: string;
22
+ meta: string;
23
+ relatedAgents: string;
24
+ status: string;
25
+ };
26
+ fks: {
27
+ agentPrompt: {
28
+ code: string;
29
+ rules: string;
30
+ multiple: boolean;
31
+ };
32
+ };
33
+ };
34
+ };
35
+ agentPrompt: {
36
+ keyPath: string;
37
+ model: DbAgentPrompt;
38
+ ts: DbAgentPrompt;
39
+ template: {
40
+ index: string;
41
+ presentation: string;
42
+ fields: {
43
+ id: string;
44
+ created_at: string;
45
+ value: string;
46
+ name: string;
47
+ code: string;
48
+ ia_lock: string;
49
+ };
50
+ fks: {};
51
+ };
52
+ };
53
+ };
54
+ export declare const schemeModelTest: IdbqModel;
55
+ export type DataModelTestFinal = DbDataModelTs<typeof schemeModelTestDb>;
56
+ export declare const idbql: import("@medyll/idae-idbql").ReadonlyCollections<IdbqModel<Record<string, Record<string, any>>>>, idbqlState: import("@medyll/idae-idbql").StateCollections<IdbqModel<Record<string, Record<string, any>>>>, idbDatabase: import("@medyll/idae-idbql").IdbqlIndexedCore<IdbqModel<Record<string, Record<string, any>>>>, idbqModel: IdbqModel<Record<string, Record<string, any>>>;
@@ -0,0 +1,58 @@
1
+ import { createIdbqDb } from '@medyll/idae-idbql';
2
+ // Schรฉma de test (copie explicite de schemeModelDb)
3
+ export const schemeModelTestDb = {
4
+ agent: {
5
+ keyPath: '++id, promptId, created_at',
6
+ model: {},
7
+ ts: {},
8
+ template: {
9
+ index: 'id',
10
+ presentation: 'name model',
11
+ fields: {
12
+ id: 'id (readonly)',
13
+ name: 'text (private)',
14
+ code: 'text',
15
+ model: 'text',
16
+ prompt: 'text-long',
17
+ created_at: 'date (private)',
18
+ ia_lock: 'boolean (private)',
19
+ agentPromptId: 'fk-agentPrompt.id (required)',
20
+ tags: 'array-of-text', // array field
21
+ meta: 'object-any', // object field
22
+ relatedAgents: 'array-of-fk-agent.id', // fk multiple
23
+ status: 'text (required readonly)'
24
+ },
25
+ fks: {
26
+ agentPrompt: {
27
+ code: 'agentPrompt',
28
+ rules: 'readonly private',
29
+ multiple: true
30
+ }
31
+ }
32
+ }
33
+ },
34
+ agentPrompt: {
35
+ keyPath: '++id, created_at',
36
+ model: {},
37
+ ts: {},
38
+ template: {
39
+ index: 'id',
40
+ presentation: 'name',
41
+ fields: {
42
+ id: 'id (readonly)',
43
+ created_at: 'date (private)',
44
+ value: 'text-long (required)',
45
+ name: 'text (required)',
46
+ code: 'text (required)',
47
+ ia_lock: 'boolean (private)'
48
+ },
49
+ fks: {}
50
+ }
51
+ }
52
+ // Ajoute ici d'autres collections si besoin pour les tests
53
+ };
54
+ export const schemeModelTest = {
55
+ ...schemeModelTestDb
56
+ };
57
+ const idbqStore = createIdbqDb(schemeModelTest, 99);
58
+ export const { idbql, idbqlState, idbDatabase, idbqModel } = idbqStore.create('idae-machine-test');
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ export * from './machine.js';
1
2
  export * from './types/appschemeTypes.js';
2
3
  export { default as Skeleton } from './fragments/Skeleton.svelte';
3
4
  export { default as Selector } from './fragments/Selector.svelte';
@@ -19,7 +20,14 @@ export { default as CollectionFks } from './form/CollectionFks.svelte';
19
20
  export { default as CollectionFieldGuess } from './form/CollectionFieldGuess.svelte';
20
21
  export { default as CollectionButton } from './form/CollectionButton.svelte';
21
22
  export * from './db/types.js';
23
+ export * from './db/testDbSchema.js';
22
24
  export * from './db/dbSchema.js';
25
+ export * from './db/dbSchema.spec.js';
26
+ export * from './db/dbFormValidate.spec.js';
23
27
  export * from './db/dbFields.js';
28
+ export * from './db/dbFields.spec.js';
29
+ export * from './db/dbCollectionValues.spec.js';
30
+ export * from './db/dbCollectionFieldValues.spec.js';
31
+ export * from './db/dbCollectionFieldForge.spec.js';
24
32
  export * from './db/dataModel.js';
25
33
  export * from './db/CrudService.js';
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  // auto exports of entry components
2
+ export * from './machine.js';
2
3
  export * from './types/appschemeTypes.js';
3
4
  export { default as Skeleton } from './fragments/Skeleton.svelte';
4
5
  export { default as Selector } from './fragments/Selector.svelte';
@@ -20,7 +21,14 @@ export { default as CollectionFks } from './form/CollectionFks.svelte';
20
21
  export { default as CollectionFieldGuess } from './form/CollectionFieldGuess.svelte';
21
22
  export { default as CollectionButton } from './form/CollectionButton.svelte';
22
23
  export * from './db/types.js';
24
+ export * from './db/testDbSchema.js';
23
25
  export * from './db/dbSchema.js';
26
+ export * from './db/dbSchema.spec.js';
27
+ export * from './db/dbFormValidate.spec.js';
24
28
  export * from './db/dbFields.js';
29
+ export * from './db/dbFields.spec.js';
30
+ export * from './db/dbCollectionValues.spec.js';
31
+ export * from './db/dbCollectionFieldValues.spec.js';
32
+ export * from './db/dbCollectionFieldForge.spec.js';
25
33
  export * from './db/dataModel.js';
26
34
  export * from './db/CrudService.js';
@@ -0,0 +1,76 @@
1
+ import { IDbCollections } from './db/dbFields.js';
2
+ import { createIdbqDb } from '@medyll/idae-idbql';
3
+ /**
4
+ * Machine: main entry point for managing the IDBQL connection and centralized data access.
5
+ */
6
+ export declare class Machine {
7
+ /**
8
+
9
+ * IDBQL (readonly collections instance)
10
+ */
11
+ idbql: ReturnType<ReturnType<typeof createIdbqDb>["create"]>["idbql"] | undefined;
12
+ /**
13
+ * IDBQL (stateful collections instance)
14
+ */
15
+ idbqlState: ReturnType<ReturnType<typeof createIdbqDb>["create"]>["idbqlState"] | undefined;
16
+ /**
17
+ * Direct access to IndexedDB (core)
18
+ */
19
+ idbDatabase: ReturnType<ReturnType<typeof createIdbqDb>["create"]>["idbDatabase"] | undefined;
20
+ /**
21
+ * IDBQL data model
22
+ */
23
+ idbqModel: ReturnType<ReturnType<typeof createIdbqDb>["create"]>["idbqModel"] | undefined;
24
+ /**
25
+ * Centralized access to schema and collection logic
26
+ */
27
+ collections: IDbCollections | undefined;
28
+ /**
29
+ * Database name
30
+ */
31
+ dbName: string;
32
+ /**
33
+ * Schema version
34
+ */
35
+ version: number;
36
+ /**
37
+ * Data model
38
+ */
39
+ model: any;
40
+ /**
41
+ * Main constructor
42
+ * @param dbName Database name (default: 'idae-machine')
43
+ * @param version Schema version (default: 1)
44
+ * @param model Data model (default: schemeModel)
45
+ */
46
+ constructor(dbName?: string, version?: number, model?: import("@medyll/idae-idbql").IdbqModel<Record<string, Record<string, any>>>);
47
+ /**
48
+ * Start the machine: initialize collections and IDBQL connection.
49
+ * @param options Optional overrides: { dbName, version, model }
50
+ */
51
+ start(options?: {
52
+ dbName?: string;
53
+ version?: number;
54
+ model?: any;
55
+ }): void;
56
+ /**
57
+ * Get the IDbCollections (schema logic) instance
58
+ */
59
+ getCollections(): IDbCollections | undefined;
60
+ /**
61
+ * Get the IDBQL (readonly) instance
62
+ */
63
+ getIdbql(): import("@medyll/idae-idbql").ReadonlyCollections<import("@medyll/idae-idbql").IdbqModel<Record<string, Record<string, any>>>> | undefined;
64
+ /**
65
+ * Get the IDBQL (stateful) instance
66
+ */
67
+ getIdbqlState(): import("@medyll/idae-idbql").StateCollections<import("@medyll/idae-idbql").IdbqModel<Record<string, Record<string, any>>>> | undefined;
68
+ /**
69
+ * Get the IndexedDB (core) instance
70
+ */
71
+ getIdbDatabase(): import("@medyll/idae-idbql").IdbqlIndexedCore<import("@medyll/idae-idbql").IdbqModel<Record<string, Record<string, any>>>> | undefined;
72
+ /**
73
+ * Get the IDBQL data model instance
74
+ */
75
+ getIdbqModel(): import("@medyll/idae-idbql").IdbqModel<Record<string, Record<string, any>>> | undefined;
76
+ }
@@ -0,0 +1,129 @@
1
+ /**
2
+ * Example usage:
3
+ *
4
+ * import { Machine } from './machine.js';
5
+ *
6
+ * // Create a new Machine instance with default parameters
7
+ * const machine = new Machine();
8
+ *
9
+ * // Start the machine (initialize collections and IDBQL connection)
10
+ * machine.start();
11
+ *
12
+ * // Access collections (schema logic)
13
+ * const collections = machine.getCollections();
14
+ *
15
+ * // Access IDBQL (readonly)
16
+ * const idbql = machine.getIdbql();
17
+ *
18
+ * // Access IDBQL (stateful)
19
+ * const idbqlState = machine.getIdbqlState();
20
+ *
21
+ * // Access IndexedDB core
22
+ * const db = machine.getIdbDatabase();
23
+ *
24
+ * // Access the IDBQL data model
25
+ * const model = machine.getIdbqModel();
26
+ */
27
+ import { schemeModel } from './db/dbSchema.js';
28
+ import { IDbCollections } from './db/dbFields.js';
29
+ import { createIdbqDb } from '@medyll/idae-idbql';
30
+ /**
31
+ * Machine: main entry point for managing the IDBQL connection and centralized data access.
32
+ */
33
+ export class Machine {
34
+ /**
35
+
36
+ * IDBQL (readonly collections instance)
37
+ */
38
+ idbql;
39
+ /**
40
+ * IDBQL (stateful collections instance)
41
+ */
42
+ idbqlState;
43
+ /**
44
+ * Direct access to IndexedDB (core)
45
+ */
46
+ idbDatabase;
47
+ /**
48
+ * IDBQL data model
49
+ */
50
+ idbqModel;
51
+ /**
52
+ * Centralized access to schema and collection logic
53
+ */
54
+ collections;
55
+ /**
56
+ * Database name
57
+ */
58
+ dbName;
59
+ /**
60
+ * Schema version
61
+ */
62
+ version;
63
+ /**
64
+ * Data model
65
+ */
66
+ model;
67
+ /**
68
+ * Main constructor
69
+ * @param dbName Database name (default: 'idae-machine')
70
+ * @param version Schema version (default: 1)
71
+ * @param model Data model (default: schemeModel)
72
+ */
73
+ constructor(dbName = 'idae-machine', version = 1, model = schemeModel) {
74
+ this.dbName = dbName;
75
+ this.version = version;
76
+ this.model = model;
77
+ this.collections = undefined;
78
+ this.idbql = undefined;
79
+ this.idbqlState = undefined;
80
+ this.idbDatabase = undefined;
81
+ this.idbqModel = undefined;
82
+ }
83
+ /**
84
+ * Start the machine: initialize collections and IDBQL connection.
85
+ * @param options Optional overrides: { dbName, version, model }
86
+ */
87
+ start(options) {
88
+ const dbName = options?.dbName ?? this.dbName;
89
+ const version = options?.version ?? this.version;
90
+ const model = options?.model ?? this.model;
91
+ this.collections = new IDbCollections(model);
92
+ const idbqStore = createIdbqDb(model, version);
93
+ const { idbql, idbqlState, idbDatabase, idbqModel } = idbqStore.create(dbName);
94
+ this.idbql = idbql;
95
+ this.idbqlState = idbqlState;
96
+ this.idbDatabase = idbDatabase;
97
+ this.idbqModel = idbqModel;
98
+ }
99
+ /**
100
+ * Get the IDbCollections (schema logic) instance
101
+ */
102
+ getCollections() {
103
+ return this.collections;
104
+ }
105
+ /**
106
+ * Get the IDBQL (readonly) instance
107
+ */
108
+ getIdbql() {
109
+ return this.idbql;
110
+ }
111
+ /**
112
+ * Get the IDBQL (stateful) instance
113
+ */
114
+ getIdbqlState() {
115
+ return this.idbqlState;
116
+ }
117
+ /**
118
+ * Get the IndexedDB (core) instance
119
+ */
120
+ getIdbDatabase() {
121
+ return this.idbDatabase;
122
+ }
123
+ /**
124
+ * Get the IDBQL data model instance
125
+ */
126
+ getIdbqModel() {
127
+ return this.idbqModel;
128
+ }
129
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@medyll/idae-machine",
3
- "version": "0.106.0",
3
+ "version": "0.108.0",
4
4
  "scripts": {
5
5
  "dev": "vite dev",
6
6
  "build": "vite build && npm run prepack",