From 40c48b4379834d3120ca359bab7c325bf53ffb64 Mon Sep 17 00:00:00 2001 From: danstarns Date: Wed, 7 Aug 2024 17:11:48 -0700 Subject: [PATCH] feat: add onRecordSet methoda --- src/data_sources/model/DataRecord.ts | 34 +++++++++++++++++- src/data_sources/model/DataRecords.ts | 6 ++-- src/data_sources/model/DataSource.ts | 6 ++-- src/data_sources/types.ts | 8 ++--- test/specs/data_sources/index.ts | 50 +++++++++++++++++++++++++-- 5 files changed, 91 insertions(+), 13 deletions(-) diff --git a/src/data_sources/model/DataRecord.ts b/src/data_sources/model/DataRecord.ts index 362538a32..d2d27897e 100644 --- a/src/data_sources/model/DataRecord.ts +++ b/src/data_sources/model/DataRecord.ts @@ -1,9 +1,10 @@ import { keys } from 'underscore'; -import { Model } from '../../common'; +import { Model, SetOptions } from '../../common'; import { DataRecordProps, DataSourcesEvents } from '../types'; import DataRecords from './DataRecords'; import DataSource from './DataSource'; import EditorModel from '../../editor/model/Editor'; +import { _StringKey } from 'backbone'; export default class DataRecord extends Model { constructor(props: T, opts = {}) { @@ -59,4 +60,35 @@ export default class DataRecord ext const paths = this.getPaths(prop); paths.forEach(path => em.trigger(`${DataSourcesEvents.path}:${path}`, { ...data, path })); } + + set>( + attributeName: Partial | A, + value?: SetOptions | T[A] | undefined, + options?: SetOptions | undefined + ): this; + set(attributeName: unknown, value?: unknown, options?: SetOptions): DataRecord { + const onRecordSet = this.dataSource?.transformers?.onRecordSet; + + if (options?.avoidTransformers) { + // @ts-ignore + super.set(attributeName, value, options); + return this; + } + + if (onRecordSet) { + const newValue = onRecordSet({ + id: this.id, + key: attributeName as string, + value, + }); + + // @ts-ignore + super.set(attributeName, newValue, options); + return this; + } else { + // @ts-ignore + super.set(attributeName, value, options); + return this; + } + } } diff --git a/src/data_sources/model/DataRecords.ts b/src/data_sources/model/DataRecords.ts index 1fb72f600..2bdfd3d06 100644 --- a/src/data_sources/model/DataRecords.ts +++ b/src/data_sources/model/DataRecords.ts @@ -16,14 +16,14 @@ export default class DataRecords extends Collection { add(model: {} | DataRecord, options?: AddRecordOptions): DataRecord; add(models: ({} | DataRecord)[], options?: AddRecordOptions): DataRecord[]; add(models: unknown, options?: AddRecordOptions): DataRecord | DataRecord[] { - const onRecordInsert = this.dataSource?.transformers?.onRecordInsert; + const onRecordAdd = this.dataSource?.transformers?.onRecordAdd; if (options?.avoidTransformers) { return super.add(models as DataRecord, options); } - if (onRecordInsert) { - const m = (Array.isArray(models) ? models : [models]).map(onRecordInsert); + if (onRecordAdd) { + const m = (Array.isArray(models) ? models : [models]).map(model => onRecordAdd({ record: model })); return super.add(m, options); } else { diff --git a/src/data_sources/model/DataSource.ts b/src/data_sources/model/DataSource.ts index c88e59dbb..333eac737 100644 --- a/src/data_sources/model/DataSource.ts +++ b/src/data_sources/model/DataSource.ts @@ -42,9 +42,9 @@ export default class DataSource extends Model { } addRecord(record: DataRecordProps, opts?: AddOptions) { - const onRecordInsert = this.transformers.onRecordInsert; - if (onRecordInsert) { - record = onRecordInsert(record); + const onRecordAdd = this.transformers.onRecordAdd; + if (onRecordAdd) { + record = onRecordAdd({ record }); } return this.records.add(record, opts); diff --git a/src/data_sources/types.ts b/src/data_sources/types.ts index 544dd86d3..094c0e841 100644 --- a/src/data_sources/types.ts +++ b/src/data_sources/types.ts @@ -21,10 +21,10 @@ export interface DataSourceProps { } export interface DataSourceTransformers { - onRecordInsert?: (record: DataRecordProps) => DataRecordProps; - onRecordUpdate?: (record: DataRecord) => DataRecord; - onRecordDelete?: (record: DataRecord) => DataRecord; - onRecordRead?: (record: DataRecord) => DataRecord; + onRecordAdd?: (args: { record: DataRecordProps }) => DataRecordProps; + onRecordSet?: (args: { id: string | number; key: string; value: any }) => any; + onRecordDelete?: (args: { record: DataRecord }) => DataRecord; + onRecordRead?: (args: { record: DataRecord }) => DataRecord; } export interface DataRecordProps extends ObjectAny { diff --git a/test/specs/data_sources/index.ts b/test/specs/data_sources/index.ts index d6f682957..74de3bf38 100644 --- a/test/specs/data_sources/index.ts +++ b/test/specs/data_sources/index.ts @@ -145,12 +145,12 @@ describe('DataSourceManager', () => { fixtures.appendChild(wrapperEl.el); }); - test('onRecordInsert', () => { + test('onRecordAdd', () => { const testDataSource: DataSourceProps = { id: 'test-data-source', records: [], transformers: { - onRecordInsert: record => { + onRecordAdd: ({ record }) => { record.content = record.content.toUpperCase(); return record; }, @@ -179,6 +179,52 @@ describe('DataSourceManager', () => { const result = ds.getRecord('id1')?.get('content'); expect(result).toBe('I LOVE GRAPES'); }); + + test('onRecordSet', () => { + const testDataSource: DataSourceProps = { + id: 'test-data-source', + records: [], + transformers: { + onRecordSet: ({ id, key, value }) => { + if (key !== 'content') { + return value; + } + + if (typeof value !== 'string') { + throw new Error('Value must be a string'); + } + + return value.toUpperCase(); + }, + }, + }; + dsm.add(testDataSource); + + const cmp = cmpRoot.append({ + tagName: 'h1', + type: 'text', + components: [ + { + type: 'data-variable', + value: 'default', + path: 'test-data-source.id1.content', + }, + ], + })[0]; + + const ds = dsm.get('test-data-source'); + const dr = ds.addRecord({ id: 'id1', content: 'i love grapes' }); + + expect(() => dr.set('content', 123)).toThrowError('Value must be a string'); + + dr.set('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('add DataSource with records', () => {