Browse Source

refactor: remove not needed transformers

feature/data-sources
danstarns 2 years ago
parent
commit
d9e1bf53b2
  1. 18
      docs/api/data_source_manager.md
  2. 7
      docs/api/datasource.md
  3. 74
      docs/modules/DataSources.md
  4. 17
      src/data_sources/index.ts
  5. 22
      src/data_sources/model/DataRecords.ts
  6. 26
      src/data_sources/model/DataSource.ts
  7. 3
      src/data_sources/types.ts
  8. 84
      test/specs/data_sources/transformers.ts

18
docs/api/data_source_manager.md

@ -88,24 +88,6 @@ Get value from data sources by key
Returns **any** const value = dsm.getValue('ds\_id.record\_id.propName', 'defaultValue');
## getContext
Retrieve the entire context of data sources.
This method aggregates all data records from all data sources and applies any
`onRecordRead` transformers defined within each data source. The result is an
object representing the current state of all data sources, where each data source
ID maps to an object containing its records' attributes. Each record is keyed by
both its index and its ID.
### Examples
```javascript
const context = dsm.getContext();
// e.g., { dataSourceId: { 0: { id: 'record1', name: 'value1' }, record1: { id: 'record1', name: 'value1' } } }
```
Returns **ObjectAny** The context of all data sources, with transformed records.
## remove
Remove data source.

7
docs/api/datasource.md

@ -21,9 +21,6 @@ const dataSource = new DataSource({
{ id: 'id1', name: 'value1' },
{ id: 'id2', name: 'value2' }
],
transformers: {
onRecordAdd: ({ record }) => ({ ...record, added: true }),
}
}, { em: editor });
dataSource.addRecord({ id: 'id3', name: 'value3' });
@ -67,7 +64,6 @@ Returns **EditorModel** The editor model.
## addRecord
Adds a new record to the data source.
If a transformer is provided for the `onRecordAdd` event, it will be applied to the record before adding it.
### Parameters
@ -79,7 +75,6 @@ Returns **DataRecord** The added data record.
## getRecord
Retrieves a record from the data source by its ID.
If a transformer is provided for the `onRecordRead` event, it will be applied to the record before returning it.
### Parameters
@ -97,7 +92,6 @@ Returns **[Array][9]<(DataRecord | [undefined][8])>** An array of data records.
## removeRecord
Removes a record from the data source by its ID.
If a transformer is provided for the `onRecordDelete` event, it will be applied before the record is removed.
### Parameters
@ -109,7 +103,6 @@ Returns **(DataRecord | [undefined][8])** The removed data record, or `undefined
## setRecords
Replaces the existing records in the data source with a new set of records.
If a transformer is provided for the `onRecordAdd` event, it will be applied to each record before adding it.
### Parameters

74
docs/modules/DataSources.md

@ -133,30 +133,9 @@ In this case, the value of the input field is bound to the DataSource value at `
Transformers in DataSources allow you to customize how data is processed during various stages of interaction with the data. The primary transformer functions include:
### 1. `onRecordAdd`
### 1. `onRecordSetValue`
This transformer is triggered when a new record is added to the data source. It allows for modification or enrichment of the record before it is stored.
#### Example Usage
```javascript
const testDataSource = {
id: 'test-data-source',
records: [],
transformers: {
onRecordAdd: ({ record }) => {
record.content = record.content.toUpperCase();
return record;
},
},
};
```
In this example, every record added will have its `content` field converted to uppercase.
### 2. `onRecordSetValue`
This transformer is invoked when a record's property is updated. It provides an opportunity to validate or transform the new value.
This transformer is invoked when a record's property is added or updated. It provides an opportunity to validate or transform the new value.
#### Example Usage
@ -178,54 +157,7 @@ const testDataSource = {
};
```
Here, the transformer ensures that the `content` field is always a string and transforms it to uppercase.
### 3. `onRecordRead`
This transformer is used when a record is read from the data source. It allows for post-processing of the data before it is returned.
#### Example Usage
```javascript
const testDataSource = {
id: 'test-data-source',
records: [],
transformers: {
onRecordRead: ({ record }) => {
const content = record.get('content');
return record.set('content', content.toUpperCase(), { avoidTransformers: true });
},
},
};
```
In this example, the `content` field of a record is converted to uppercase when read.
### 4. `onRecordDelete`
This transformer is invoked when a record is about to be deleted. It can be used to prevent deletion or to perform additional actions before the record is removed.
#### Example Usage
```javascript
const testDataSource = {
id: 'test-data-source',
records: [],
transformers: {
onRecordDelete: ({ record }) => {
if (record.get('content') === 'i love grapes') {
throw new Error('Cannot delete record with content "i love grapes"');
}
},
},
};
```
In this scenario, a record with the `content` of `"i love grapes"` cannot be deleted.
---
These transformers can be customized to meet specific needs, ensuring that data is managed and manipulated in a way that fits your application requirements.
In this example, the `onRecordSetValue` transformer ensures that the `content` property is always an uppercase string.
## Benefits of Using DataSources

17
src/data_sources/index.ts

@ -96,23 +96,10 @@ export default class DataSourceManager extends ItemManagerModule<ModuleConfig, D
return get(this.getContext(), key, defValue);
}
/**
* Retrieve the entire context of data sources.
* This method aggregates all data records from all data sources and applies any
* `onRecordRead` transformers defined within each data source. The result is an
* object representing the current state of all data sources, where each data source
* ID maps to an object containing its records' attributes. Each record is keyed by
* both its index and its ID.
*
* @returns {ObjectAny} - The context of all data sources, with transformed records.
* @example
* const context = dsm.getContext();
* // e.g., { dataSourceId: { 0: { id: 'record1', name: 'value1' }, record1: { id: 'record1', name: 'value1' } } }
*/
getContext() {
private getContext() {
return this.all.reduce((acc, ds) => {
acc[ds.id] = ds.records.reduce((accR, dr, i) => {
const dataRecord = ds.transformers.onRecordRead ? ds.transformers.onRecordRead({ record: dr }) : dr;
const dataRecord = dr;
accR[i] = dataRecord.attributes;
accR[dataRecord.id || i] = dataRecord.attributes;

22
src/data_sources/model/DataRecords.ts

@ -1,10 +1,8 @@
import { AddOptions, Collection } from '../../common';
import { Collection } from '../../common';
import { DataRecordProps } from '../types';
import DataRecord from './DataRecord';
import DataSource from './DataSource';
type AddRecordOptions = AddOptions & { avoidTransformers?: boolean };
export default class DataRecords extends Collection<DataRecord> {
dataSource: DataSource;
@ -12,24 +10,6 @@ export default class DataRecords extends Collection<DataRecord> {
super(models, options);
this.dataSource = options.dataSource;
}
add(model: {} | DataRecord<DataRecordProps>, options?: AddRecordOptions): DataRecord<DataRecordProps>;
add(models: ({} | DataRecord<DataRecordProps>)[], options?: AddRecordOptions): DataRecord<DataRecordProps>[];
add(models: unknown, options?: AddRecordOptions): DataRecord<DataRecordProps> | DataRecord<DataRecordProps>[] {
const onRecordAdd = this.dataSource?.transformers?.onRecordAdd;
if (options?.avoidTransformers) {
return super.add(models as DataRecord<DataRecordProps>, options);
}
if (onRecordAdd) {
const m = (Array.isArray(models) ? models : [models]).map((model) => onRecordAdd({ record: model }));
return super.add(m, options);
} else {
return super.add(models as DataRecord<DataRecordProps>, options);
}
}
}
DataRecords.prototype.model = DataRecord;

26
src/data_sources/model/DataSource.ts

@ -18,9 +18,6 @@
* { id: 'id1', name: 'value1' },
* { id: 'id2', name: 'value2' }
* ],
* transformers: {
* onRecordAdd: ({ record }) => ({ ...record, added: true }),
* }
* }, { em: editor });
*
* dataSource.addRecord({ id: 'id3', name: 'value3' });
@ -113,7 +110,6 @@ export default class DataSource extends Model<DataSourceProps> {
/**
* Adds a new record to the data source.
* If a transformer is provided for the `onRecordAdd` event, it will be applied to the record before adding it.
*
* @param {DataRecordProps} record - The properties of the record to add.
* @param {AddOptions} [opts] - Options to apply when adding the record.
@ -121,29 +117,18 @@ export default class DataSource extends Model<DataSourceProps> {
* @name addRecord
*/
addRecord(record: DataRecordProps, opts?: AddOptions) {
const onRecordAdd = this.transformers.onRecordAdd;
if (onRecordAdd) {
record = onRecordAdd({ record });
}
return this.records.add(record, opts);
}
/**
* Retrieves a record from the data source by its ID.
* If a transformer is provided for the `onRecordRead` event, it will be applied to the record before returning it.
*
* @param {string | number} id - The ID of the record to retrieve.
* @returns {DataRecord | undefined} The data record, or `undefined` if no record is found with the given ID.
* @name getRecord
*/
getRecord(id: string | number): DataRecord | undefined {
const onRecordRead = this.transformers.onRecordRead;
const record = this.records.get(id);
if (record && onRecordRead) {
return onRecordRead({ record });
}
return record;
}
@ -160,7 +145,6 @@ export default class DataSource extends Model<DataSourceProps> {
/**
* Removes a record from the data source by its ID.
* If a transformer is provided for the `onRecordDelete` event, it will be applied before the record is removed.
*
* @param {string | number} id - The ID of the record to remove.
* @param {RemoveOptions} [opts] - Options to apply when removing the record.
@ -168,19 +152,11 @@ export default class DataSource extends Model<DataSourceProps> {
* @name removeRecord
*/
removeRecord(id: string | number, opts?: RemoveOptions): DataRecord | undefined {
const onRecordDelete = this.transformers.onRecordDelete;
const record = this.getRecord(id);
if (record && onRecordDelete) {
onRecordDelete({ record });
}
return this.records.remove(id, opts);
}
/**
* Replaces the existing records in the data source with a new set of records.
* If a transformer is provided for the `onRecordAdd` event, it will be applied to each record before adding it.
*
* @param {Array<DataRecordProps>} records - An array of data record properties to set.
* @returns {Array<DataRecord>} An array of the added data records.
@ -190,7 +166,7 @@ export default class DataSource extends Model<DataSourceProps> {
this.records.reset([], { silent: true });
records.forEach((record) => {
this.records.add(record, { avoidTransformers: true });
this.records.add(record);
});
}
}

3
src/data_sources/types.ts

@ -33,10 +33,7 @@ export interface DataSourceProps {
}
export interface DataSourceTransformers {
onRecordAdd?: (args: { record: DataRecordProps }) => DataRecordProps;
onRecordSetValue?: (args: { id: string | number; key: string; value: any }) => any;
onRecordDelete?: (args: { record: DataRecord }) => void;
onRecordRead?: (args: { record: DataRecord }) => DataRecord;
}
/**{START_EVENTS}*/

84
test/specs/data_sources/transformers.ts

@ -34,14 +34,17 @@ describe('DataSource Transformers', () => {
em.destroy();
});
test('onRecordAdd', () => {
test('should assert that onRecordSetValue is called when adding a record', () => {
const testDataSource: DataSourceProps = {
id: 'test-data-source',
records: [],
transformers: {
onRecordAdd: ({ record }) => {
record.content = record.content.toUpperCase();
return record;
onRecordSetValue: ({ key, value }) => {
if (key !== 'content') {
return value;
}
return (value as string).toUpperCase();
},
},
};
@ -69,7 +72,7 @@ describe('DataSource Transformers', () => {
expect(result).toBe('I LOVE GRAPES');
});
test('onRecordSetValue', () => {
test('should assert that onRecordSetValue is called when setting a value on a record', () => {
const testDataSource: DataSourceProps = {
id: 'test-data-source',
records: [],
@ -115,75 +118,4 @@ describe('DataSource Transformers', () => {
const result = ds.getRecord('id1')?.get('content');
expect(result).toBe('I LOVE GRAPES');
});
test('onRecordRead', () => {
const testDataSource: DataSourceProps = {
id: 'test-data-source',
records: [],
transformers: {
onRecordRead: ({ record }) => {
const content = record.get('content');
return record.set('content', content.toUpperCase(), { avoidTransformers: true });
},
},
};
dsm.add(testDataSource);
const cmp = cmpRoot.append({
tagName: 'h1',
type: 'text',
components: [
{
type: DataVariableType,
defaultValue: 'default',
path: 'test-data-source.id1.content',
},
],
})[0];
const ds = dsm.get('test-data-source');
ds.addRecord({ id: 'id1', content: 'i love grapes' });
const el = cmp.getEl();
expect(el?.innerHTML).toContain('I LOVE GRAPES');
const result = ds.getRecord('id1')?.get('content');
expect(result).toBe('I LOVE GRAPES');
});
test('onRecordDelete', () => {
const testDataSource: DataSourceProps = {
id: 'test-data-source',
records: [],
transformers: {
onRecordDelete: ({ record }) => {
if (record.get('content') === 'i love grapes') {
throw new Error('Cannot delete record with content "i love grapes"');
}
},
},
};
dsm.add(testDataSource);
const cmp = cmpRoot.append({
tagName: 'h1',
type: 'text',
components: [
{
type: DataVariableType,
defaultValue: 'default',
path: 'test-data-source.id1.content',
},
],
})[0];
const ds = dsm.get('test-data-source');
ds.addRecord({ id: 'id1', content: 'i love grapes' });
let el = cmp.getEl();
expect(el?.innerHTML).toContain('i love grapes');
expect(() => ds.removeRecord('id1')).toThrowError('Cannot delete record with content "i love grapes"');
});
});

Loading…
Cancel
Save