From 68ec5135cca467682182f759ea885844dc89a703 Mon Sep 17 00:00:00 2001 From: mProjectsCode Date: Mon, 26 Sep 2022 15:44:12 +0200 Subject: [PATCH] property mapping validation #48 --- src/main.ts | 8 +- src/settings/PropertyMapper.ts | 10 +- src/settings/PropertyMapping.ts | 111 ++++++++++++++++-- .../PropertyMappingModelsComponent.svelte | 22 +++- src/settings/Settings.ts | 7 +- src/utils/Utils.ts | 11 ++ 6 files changed, 146 insertions(+), 23 deletions(-) diff --git a/src/main.ts b/src/main.ts index 4af8c5b..cb5e80d 100644 --- a/src/main.ts +++ b/src/main.ts @@ -507,15 +507,15 @@ export default class MediaDbPlugin extends Plugin { for (const defaultProperty of defaultPropertyMappingModel.properties) { let newProperty = newPropertyMappingModel.properties.find(x => x.property === defaultProperty.property); if (newProperty === undefined) { + // default property is an instance newProperties.push(defaultProperty); } else { - newProperties.push(newProperty); + // newProperty is just an object and take locked status from default property + newProperties.push(new PropertyMapping(newProperty.property, newProperty.newProperty, newProperty.mapping, defaultProperty.locked)); } } - newPropertyMappingModel.properties = newProperties; - - newPropertyMappings.push(newPropertyMappingModel); + newPropertyMappings.push(new PropertyMappingModel(newPropertyMappingModel.type, newProperties)); } } loadedSettings.propertyMappingModels = newPropertyMappings; diff --git a/src/settings/PropertyMapper.ts b/src/settings/PropertyMapper.ts index 12aa4e2..a1e41a6 100644 --- a/src/settings/PropertyMapper.ts +++ b/src/settings/PropertyMapper.ts @@ -16,15 +16,23 @@ export class PropertyMapper { * @param obj */ convertObject(obj: object): object { + console.log('test1'); + if (!obj.hasOwnProperty('type')) { return obj; } + console.log('test2'); // @ts-ignore - if (MEDIA_TYPES.contains(obj.type)) { + console.log(obj.type); + + // @ts-ignore + if (MEDIA_TYPES.filter(x => x.toString() == obj.type).length < 1) { return obj; } + console.log('test3'); + // @ts-ignore const propertyMappings = this.plugin.settings.propertyMappingModels.find(x => x.type === obj.type).properties; diff --git a/src/settings/PropertyMapping.ts b/src/settings/PropertyMapping.ts index e68bdfc..a221918 100644 --- a/src/settings/PropertyMapping.ts +++ b/src/settings/PropertyMapping.ts @@ -1,4 +1,4 @@ -import {containsOnlyLettersAndUnderscores} from '../utils/Utils'; +import {containsOnlyLettersAndUnderscores, PropertyMappingNameConflictError, PropertyMappingValidationError} from '../utils/Utils'; import {MediaType} from '../utils/MediaType'; export enum PropertyMappingOption { @@ -9,9 +9,73 @@ export enum PropertyMappingOption { export const propertyMappingOptions = [PropertyMappingOption.Default, PropertyMappingOption.Map, PropertyMappingOption.Remove]; -export interface PropertyMappingModel { - type: MediaType, - properties: PropertyMapping[], +export class PropertyMappingModel { + type: MediaType; + properties: PropertyMapping[]; + + constructor(type: MediaType, properties?: PropertyMapping[]) { + this.type = type; + this.properties = properties ?? []; + } + + validate(): { res: boolean, err?: Error } { + // check properties + for (const property of this.properties) { + const propertyValidation = property.validate(); + if (!propertyValidation.res) { + return { + res: false, + err: propertyValidation.err, + }; + } + } + + // check for name collisions + for (const property of this.getMappedProperties()) { + const propertiesWithSameTarget = this.getMappedProperties().filter(x => x.newProperty === property.newProperty); + if (propertiesWithSameTarget.length === 0) { + // if we get there, then something in this code is wrong + } else if (propertiesWithSameTarget.length === 1) { + // all good + } else { + // two or more properties are mapped to the same property + return { + res: false, + err: new PropertyMappingNameConflictError(`Multiple remapped properties (${propertiesWithSameTarget.map(x => x.toString()).toString()}) may not share the same name.`), + }; + } + } + // remapped properties may not have the same name as any original property + for (const property of this.getMappedProperties()) { + const propertiesWithSameTarget = this.properties.filter(x => x.newProperty === property.property); + if (propertiesWithSameTarget.length === 0) { + // all good + } else { + // a mapped property shares the same name with an original property + return { + res: false, + err: new PropertyMappingNameConflictError(`Remapped property (${property}) may not share it's new name with an existing property.`), + }; + } + } + + return { + res: true, + }; + } + + getMappedProperties() { + return this.properties.filter(x => x.mapping === PropertyMappingOption.Map); + } + + copy(): PropertyMappingModel { + const copy = new PropertyMappingModel(this.type); + for (const property of this.properties) { + const propertyCopy = new PropertyMapping(property.property, property.newProperty, property.mapping, property.locked); + copy.properties.push(propertyCopy); + } + return copy; + } } export class PropertyMapping { @@ -49,16 +113,47 @@ export class PropertyMapping { */ } - validate(): string { + validate(): { res: boolean, err?: Error } { + // locked property may only be default + if (this.locked) { + if (this.mapping === PropertyMappingOption.Remove) { + return { + res: false, + err: new PropertyMappingValidationError(`Error in property mapping "${this.toString()}": locked property may not be removed.`), + }; + } + if (this.mapping === PropertyMappingOption.Map) { + return { + res: false, + err: new PropertyMappingValidationError(`Error in property mapping "${this.toString()}": locked property may not be remapped.`), + }; + } + } + + if (this.mapping === PropertyMappingOption.Default) { + return {res: true}; + } + if (this.mapping === PropertyMappingOption.Remove) { + return {res: true}; + } + if (!this.property || !containsOnlyLettersAndUnderscores(this.property)) { - return `Error in conversion rule "${this.toString()}": property may not be empty and only contain letters and underscores.`; + return { + res: false, + err: new PropertyMappingValidationError(`Error in property mapping "${this.toString()}": property may not be empty and only contain letters and underscores.`), + }; } if (!this.newProperty || !containsOnlyLettersAndUnderscores(this.newProperty)) { - return `Error in conversion rule "${this.toString()}": new property may not be empty and only contain letters and underscores.`; + return { + res: false, + err: new PropertyMappingValidationError(`Error in property mapping "${this.toString()}": new property may not be empty and only contain letters and underscores.`), + }; } - return ''; + return { + res: true, + }; } toString(): string { diff --git a/src/settings/PropertyMappingModelsComponent.svelte b/src/settings/PropertyMappingModelsComponent.svelte index 1e14b20..f5d1af8 100644 --- a/src/settings/PropertyMappingModelsComponent.svelte +++ b/src/settings/PropertyMappingModelsComponent.svelte @@ -49,10 +49,15 @@ margin: 0; } - .media-db-plugin-property-binding-to { + .media-db-plugin-property-mapping-to { display: flex; align-items: center; } + + .media-db-plugin-property-mapping-validation { + color: var(--text-error); + margin-bottom: 5px; + }
@@ -81,18 +86,25 @@ {#if property.mapping === PropertyMappingOption.Map} -
+
{/if} {/if}
- { /each } + { /each }
- - { /each } + { /each }
{JSON.stringify(models, null, 4)}
diff --git a/src/settings/Settings.ts b/src/settings/Settings.ts index 30d31c6..7fe871a 100644 --- a/src/settings/Settings.ts +++ b/src/settings/Settings.ts @@ -142,10 +142,7 @@ export function getDefaultSettings(plugin: MediaDbPlugin): MediaDbPluginSettings // console.log(metadataObj); // console.log(model); - const propertyMappingModel: PropertyMappingModel = { - type: mediaType, - properties: [], - }; + const propertyMappingModel: PropertyMappingModel = new PropertyMappingModel(mediaType); for (const key of Object.keys(metadataObj)) { propertyMappingModel.properties.push( @@ -486,7 +483,7 @@ export class MediaDbSettingTab extends PluginSettingTab { new PropertyMappingModelsComponent({ target: this.containerEl, props: { - models: JSON.parse(JSON.stringify(this.plugin.settings.propertyMappingModels)), + models: this.plugin.settings.propertyMappingModels.map(x => x.copy()), save: (model: PropertyMappingModel) => { let propertyMappingModels: PropertyMappingModel[] = []; diff --git a/src/utils/Utils.ts b/src/utils/Utils.ts index e8f67ac..37426df 100644 --- a/src/utils/Utils.ts +++ b/src/utils/Utils.ts @@ -179,3 +179,14 @@ export function capitalizeFirstLetter(string: string): string { // credits to phibr0 on discord export const ICON_LIST = ['activity', 'airplay', 'alarm-check', 'alarm-clock-off', 'alarm-clock', 'alarm-minus', 'alarm-plus', 'album', 'alert-circle', 'alert-octagon', 'alert-triangle', 'align-center-horizontal', 'align-center-vertical', 'align-center', 'align-end-horizontal', 'align-end-vertical', 'align-horizontal-distribute-center', 'align-horizontal-distribute-end', 'align-horizontal-distribute-start', 'align-horizontal-justify-center', 'align-horizontal-justify-end', 'align-horizontal-justify-start', 'align-horizontal-space-around', 'align-horizontal-space-between', 'align-justify', 'align-left', 'align-right', 'align-start-horizontal', 'align-start-vertical', 'align-vertical-distribute-center', 'align-vertical-distribute-end', 'align-vertical-distribute-start', 'align-vertical-justify-center', 'align-vertical-justify-end', 'align-vertical-justify-start', 'align-vertical-space-around', 'align-vertical-space-between', 'anchor', 'aperture', 'archive', 'arrow-big-down', 'arrow-big-left', 'arrow-big-right', 'arrow-big-up', 'arrow-down-circle', 'arrow-down-left', 'arrow-down-right', 'arrow-down', 'arrow-left-circle', 'arrow-left-right', 'arrow-left', 'arrow-right-circle', 'arrow-right', 'arrow-up-circle', 'arrow-up-left', 'arrow-up-right', 'arrow-up', 'asterisk', 'at-sign', 'award', 'axe', 'banknote', 'bar-chart-2', 'bar-chart', 'baseline', 'battery-charging', 'battery-full', 'battery-low', 'battery-medium', 'battery', 'beaker', 'bell-minus', 'bell-off', 'bell-plus', 'bell-ring', 'bell', 'bike', 'binary', 'bitcoin', 'bluetooth-connected', 'bluetooth-off', 'bluetooth-searching', 'bluetooth', 'bold', 'book-open', 'book', 'bookmark-minus', 'bookmark-plus', 'bookmark', 'bot', 'box-select', 'box', 'briefcase', 'brush', 'bug', 'building-2', 'building', 'bus', 'calculator', 'calendar', 'camera-off', 'camera', 'car', 'carrot', 'cast', 'check-circle-2', 'check-circle', 'check-square', 'check', 'chevron-down', 'chevron-first', 'chevron-last', 'chevron-left', 'chevron-right', 'chevron-up', 'chevrons-down-up', 'chevrons-down', 'chevrons-left', 'chevrons-right', 'chevrons-up-down', 'chevrons-up', 'chrome', 'circle-slashed', 'circle', 'clipboard-check', 'clipboard-copy', 'clipboard-list', 'clipboard-x', 'clipboard', 'clock-1', 'clock-10', 'clock-11', 'clock-12', 'clock-2', 'clock-3', 'clock-4', 'clock-5', 'clock-6', 'clock-7', 'clock-8', 'clock-9', 'clock', 'cloud-drizzle', 'cloud-fog', 'cloud-hail', 'cloud-lightning', 'cloud-moon', 'cloud-off', 'cloud-rain-wind', 'cloud-rain', 'cloud-snow', 'cloud-sun', 'cloud', 'cloudy', 'clover', 'code-2', 'code', 'codepen', 'codesandbox', 'coffee', 'coins', 'columns', 'command', 'compass', 'contact', 'contrast', 'cookie', 'copy', 'copyleft', 'copyright', 'corner-down-left', 'corner-down-right', 'corner-left-down', 'corner-left-up', 'corner-right-down', 'corner-right-up', 'corner-up-left', 'corner-up-right', 'cpu', 'credit-card', 'crop', 'cross', 'crosshair', 'crown', 'currency', 'database', 'delete', 'dice-1', 'dice-2', 'dice-3', 'dice-4', 'dice-5', 'dice-6', 'disc', 'divide-circle', 'divide-square', 'divide', 'dollar-sign', 'download-cloud', 'download', 'dribbble', 'droplet', 'droplets', 'drumstick', 'edit-2', 'edit-3', 'edit', 'egg', 'equal-not', 'equal', 'eraser', 'euro', 'expand', 'external-link', 'eye-off', 'eye', 'facebook', 'fast-forward', 'feather', 'figma', 'file-check-2', 'file-check', 'file-code', 'file-digit', 'file-input', 'file-minus-2', 'file-minus', 'file-output', 'file-plus-2', 'file-plus', 'file-search', 'file-text', 'file-x-2', 'file-x', 'file', 'files', 'film', 'filter', 'flag-off', 'flag-triangle-left', 'flag-triangle-right', 'flag', 'flame', 'flashlight-off', 'flashlight', 'flask-conical', 'flask-round', 'folder-minus', 'folder-open', 'folder-plus', 'folder', 'form-input', 'forward', 'frame', 'framer', 'frown', 'function-square', 'gamepad-2', 'gamepad', 'gauge', 'gavel', 'gem', 'ghost', 'gift', 'git-branch-plus', 'git-branch', 'git-commit', 'git-fork', 'git-merge', 'git-pull-request', 'github', 'gitlab', 'glasses', 'globe-2', 'globe', 'grab', 'graduation-cap', 'grid', 'grip-horizontal', 'grip-vertical', 'hammer', 'hand-metal', 'hand', 'hard-drive', 'hard-hat', 'hash', 'haze', 'headphones', 'heart', 'help-circle', 'hexagon', 'highlighter', 'history', 'home', 'image-minus', 'image-off', 'image-plus', 'image', 'import', 'inbox', 'indent', 'indian-rupee', 'infinity', 'info', 'inspect', 'instagram', 'italic', 'japanese-yen', 'key', 'keyboard', 'landmark', 'languages', 'laptop-2', 'laptop', 'lasso-select', 'lasso', 'layers', 'layout-dashboard', 'layout-grid', 'layout-list', 'layout-template', 'layout', 'library', 'life-buoy', 'lightbulb-off', 'lightbulb', 'link-2-off', 'link-2', 'link', 'linkedin', 'list-checks', 'list-minus', 'list-ordered', 'list-plus', 'list-x', 'list', 'loader-2', 'loader', 'locate-fixed', 'locate-off', 'locate', 'lock', 'log-in', 'log-out', 'mail', 'map-pin', 'map', 'maximize-2', 'maximize', 'megaphone', 'meh', 'menu', 'message-circle', 'message-square', 'mic-off', 'mic', 'minimize-2', 'minimize', 'minus-circle', 'minus-square', 'minus', 'monitor-off', 'monitor-speaker', 'monitor', 'moon', 'more-horizontal', 'more-vertical', 'mountain-snow', 'mountain', 'mouse-pointer-2', 'mouse-pointer-click', 'mouse-pointer', 'mouse', 'move-diagonal-2', 'move-diagonal', 'move-horizontal', 'move-vertical', 'move', 'music', 'navigation-2', 'navigation', 'network', 'octagon', 'option', 'outdent', 'package-check', 'package-minus', 'package-plus', 'package-search', 'package-x', 'package', 'palette', 'palmtree', 'paperclip', 'pause-circle', 'pause-octagon', 'pause', 'pen-tool', 'pencil', 'percent', 'person-standing', 'phone-call', 'phone-forwarded', 'phone-incoming', 'phone-missed', 'phone-off', 'phone-outgoing', 'phone', 'pie-chart', 'piggy-bank', 'pin', 'pipette', 'plane', 'play-circle', 'play', 'plug-zap', 'plus-circle', 'plus-square', 'plus', 'pocket', 'podcast', 'pointer', 'pound-sterling', 'power-off', 'power', 'printer', 'qr-code', 'quote', 'radio-receiver', 'radio', 'redo', 'refresh-ccw', 'refresh-cw', 'regex', 'repeat-1', 'repeat', 'reply-all', 'reply', 'rewind', 'rocket', 'rocking-chair', 'rotate-ccw', 'rotate-cw', 'rss', 'ruler', 'russian-ruble', 'save', 'scale', 'scan-line', 'scan', 'scissors', 'screen-share-off', 'screen-share', 'search', 'send', 'separator-horizontal', 'separator-vertical', 'server-crash', 'server-off', 'server', 'settings-2', 'settings', 'share-2', 'share', 'sheet', 'shield-alert', 'shield-check', 'shield-close', 'shield-off', 'shield', 'shirt', 'shopping-bag', 'shopping-cart', 'shovel', 'shrink', 'shuffle', 'sidebar-close', 'sidebar-open', 'sidebar', 'sigma', 'signal-high', 'signal-low', 'signal-medium', 'signal-zero', 'signal', 'skip-back', 'skip-forward', 'skull', 'slack', 'slash', 'sliders', 'smartphone-charging', 'smartphone', 'smile', 'snowflake', 'sort-asc', 'sort-desc', 'speaker', 'sprout', 'square', 'star-half', 'star', 'stop-circle', 'stretch-horizontal', 'stretch-vertical', 'strikethrough', 'subscript', 'sun', 'sunrise', 'sunset', 'superscript', 'swiss-franc', 'switch-camera', 'table', 'tablet', 'tag', 'target', 'tent', 'terminal-square', 'terminal', 'text-cursor-input', 'text-cursor', 'thermometer-snowflake', 'thermometer-sun', 'thermometer', 'thumbs-down', 'thumbs-up', 'ticket', 'timer-off', 'timer-reset', 'timer', 'toggle-left', 'toggle-right', 'tornado', 'trash-2', 'trash', 'trello', 'trending-down', 'trending-up', 'triangle', 'truck', 'tv-2', 'tv', 'twitch', 'twitter', 'type', 'umbrella', 'underline', 'undo', 'unlink-2', 'unlink', 'unlock', 'upload-cloud', 'upload', 'user-check', 'user-minus', 'user-plus', 'user-x', 'user', 'users', 'verified', 'vibrate', 'video-off', 'video', 'view', 'voicemail', 'volume-1', 'volume-2', 'volume-x', 'volume', 'wallet', 'wand', 'watch', 'waves', 'webcam', 'wifi-off', 'wifi', 'wind', 'wrap-text', 'wrench', 'x-circle', 'x-octagon', 'x-square', 'x', 'youtube', 'zap-off', 'zap', 'zoom-in', 'zoom-out', 'search-large', 'search', 'activity', 'airplay', 'alarm-check', 'alarm-clock-off', 'alarm-clock', 'alarm-minus', 'alarm-plus', 'album', 'alert-circle', 'alert-octagon', 'alert-triangle', 'align-center-horizontal', 'align-center-vertical', 'align-center', 'align-end-horizontal', 'align-end-vertical', 'align-horizontal-distribute-center', 'align-horizontal-distribute-end', 'align-horizontal-distribute-start', 'align-horizontal-justify-center', 'align-horizontal-justify-end', 'align-horizontal-justify-start', 'align-horizontal-space-around', 'align-horizontal-space-between', 'align-justify', 'align-left', 'align-right', 'align-start-horizontal', 'align-start-vertical', 'align-vertical-distribute-center', 'align-vertical-distribute-end', 'align-vertical-distribute-start', 'align-vertical-justify-center', 'align-vertical-justify-end', 'align-vertical-justify-start', 'align-vertical-space-around', 'align-vertical-space-between', 'anchor', 'aperture', 'archive', 'arrow-big-down', 'arrow-big-left', 'arrow-big-right', 'arrow-big-up', 'arrow-down-circle', 'arrow-down-left', 'arrow-down-right', 'arrow-down', 'arrow-left-circle', 'arrow-left-right', 'arrow-left', 'arrow-right-circle', 'arrow-right', 'arrow-up-circle', 'arrow-up-left', 'arrow-up-right', 'arrow-up', 'asterisk', 'at-sign', 'award', 'axe', 'banknote', 'bar-chart-2', 'bar-chart', 'baseline', 'battery-charging', 'battery-full', 'battery-low', 'battery-medium', 'battery', 'beaker', 'bell-minus', 'bell-off', 'bell-plus', 'bell-ring', 'bell', 'bike', 'binary', 'bitcoin', 'bluetooth-connected', 'bluetooth-off', 'bluetooth-searching', 'bluetooth', 'bold', 'book-open', 'book', 'bookmark-minus', 'bookmark-plus', 'bookmark', 'bot', 'box-select', 'box', 'briefcase', 'brush', 'bug', 'building-2', 'building', 'bus', 'calculator', 'calendar', 'camera-off', 'camera', 'car', 'carrot', 'cast', 'check-circle-2', 'check-circle', 'check-square', 'check', 'chevron-down', 'chevron-first', 'chevron-last', 'chevron-left', 'chevron-right', 'chevron-up', 'chevrons-down-up', 'chevrons-down', 'chevrons-left', 'chevrons-right', 'chevrons-up-down', 'chevrons-up', 'chrome', 'circle-slashed', 'circle', 'clipboard-check', 'clipboard-copy', 'clipboard-list', 'clipboard-x', 'clipboard', 'clock-1', 'clock-10', 'clock-11', 'clock-12', 'clock-2', 'clock-3', 'clock-4', 'clock-5', 'clock-6', 'clock-7', 'clock-8', 'clock-9', 'lucide-clock', 'cloud-drizzle', 'cloud-fog', 'cloud-hail', 'cloud-lightning', 'cloud-moon', 'cloud-off', 'cloud-rain-wind', 'cloud-rain', 'cloud-snow', 'cloud-sun', 'lucide-cloud', 'cloudy', 'clover', 'code-2', 'code', 'codepen', 'codesandbox', 'coffee', 'coins', 'columns', 'command', 'compass', 'contact', 'contrast', 'cookie', 'copy', 'copyleft', 'copyright', 'corner-down-left', 'corner-down-right', 'corner-left-down', 'corner-left-up', 'corner-right-down', 'corner-right-up', 'corner-up-left', 'corner-up-right', 'cpu', 'credit-card', 'crop', 'lucide-cross', 'crosshair', 'crown', 'currency', 'database', 'delete', 'dice-1', 'dice-2', 'dice-3', 'dice-4', 'dice-5', 'dice-6', 'disc', 'divide-circle', 'divide-square', 'divide', 'dollar-sign', 'download-cloud', 'download', 'dribbble', 'droplet', 'droplets', 'drumstick', 'edit-2', 'edit-3', 'edit', 'egg', 'equal-not', 'equal', 'eraser', 'euro', 'expand', 'external-link', 'eye-off', 'eye', 'facebook', 'fast-forward', 'feather', 'figma', 'file-check-2', 'file-check', 'file-code', 'file-digit', 'file-input', 'file-minus-2', 'file-minus', 'file-output', 'file-plus-2', 'file-plus', 'file-search', 'file-text', 'file-x-2', 'file-x', 'file', 'files', 'film', 'filter', 'flag-off', 'flag-triangle-left', 'flag-triangle-right', 'flag', 'flame', 'flashlight-off', 'flashlight', 'flask-conical', 'flask-round', 'folder-minus', 'folder-open', 'folder-plus', 'lucide-folder', 'form-input', 'forward', 'frame', 'framer', 'frown', 'function-square', 'gamepad-2', 'gamepad', 'gauge', 'gavel', 'gem', 'ghost', 'gift', 'git-branch-plus', 'git-branch', 'git-commit', 'git-fork', 'git-merge', 'git-pull-request', 'github', 'gitlab', 'glasses', 'globe-2', 'globe', 'grab', 'graduation-cap', 'grid', 'grip-horizontal', 'grip-vertical', 'hammer', 'hand-metal', 'hand', 'hard-drive', 'hard-hat', 'hash', 'haze', 'headphones', 'heart', 'help-circle', 'hexagon', 'highlighter', 'history', 'home', 'image-minus', 'image-off', 'image-plus', 'image', 'import', 'inbox', 'indent', 'indian-rupee', 'infinity', 'lucide-info', 'inspect', 'instagram', 'italic', 'japanese-yen', 'key', 'keyboard', 'landmark', 'lucide-languages', 'laptop-2', 'laptop', 'lasso-select', 'lasso', 'layers', 'layout-dashboard', 'layout-grid', 'layout-list', 'layout-template', 'layout', 'library', 'life-buoy', 'lightbulb-off', 'lightbulb', 'link-2-off', 'link-2', 'lucide-link', 'linkedin', 'list-checks', 'list-minus', 'list-ordered', 'list-plus', 'list-x', 'list', 'loader-2', 'loader', 'locate-fixed', 'locate-off', 'locate', 'lock', 'log-in', 'log-out', 'mail', 'map-pin', 'map', 'maximize-2', 'maximize', 'megaphone', 'meh', 'menu', 'message-circle', 'message-square', 'mic-off', 'mic', 'minimize-2', 'minimize', 'minus-circle', 'minus-square', 'minus', 'monitor-off', 'monitor-speaker', 'monitor', 'moon', 'more-horizontal', 'more-vertical', 'mountain-snow', 'mountain', 'mouse-pointer-2', 'mouse-pointer-click', 'mouse-pointer', 'mouse', 'move-diagonal-2', 'move-diagonal', 'move-horizontal', 'move-vertical', 'move', 'music', 'navigation-2', 'navigation', 'network', 'octagon', 'option', 'outdent', 'package-check', 'package-minus', 'package-plus', 'package-search', 'package-x', 'package', 'palette', 'palmtree', 'paperclip', 'pause-circle', 'pause-octagon', 'pause', 'pen-tool', 'lucide-pencil', 'percent', 'person-standing', 'phone-call', 'phone-forwarded', 'phone-incoming', 'phone-missed', 'phone-off', 'phone-outgoing', 'phone', 'pie-chart', 'piggy-bank', 'lucide-pin', 'pipette', 'plane', 'play-circle', 'play', 'plug-zap', 'plus-circle', 'plus-square', 'plus', 'pocket', 'podcast', 'pointer', 'pound-sterling', 'power-off', 'power', 'printer', 'qr-code', 'quote', 'radio-receiver', 'radio', 'redo', 'refresh-ccw', 'refresh-cw', 'regex', 'repeat-1', 'repeat', 'reply-all', 'reply', 'rewind', 'rocket', 'rocking-chair', 'rotate-ccw', 'rotate-cw', 'rss', 'ruler', 'russian-ruble', 'save', 'scale', 'scan-line', 'scan', 'scissors', 'screen-share-off', 'screen-share', 'lucide-search', 'send', 'separator-horizontal', 'separator-vertical', 'server-crash', 'server-off', 'server', 'settings-2', 'settings', 'share-2', 'share', 'sheet', 'shield-alert', 'shield-check', 'shield-close', 'shield-off', 'shield', 'shirt', 'shopping-bag', 'shopping-cart', 'shovel', 'shrink', 'shuffle', 'sidebar-close', 'sidebar-open', 'sidebar', 'sigma', 'signal-high', 'signal-low', 'signal-medium', 'signal-zero', 'signal', 'skip-back', 'skip-forward', 'skull', 'slack', 'slash', 'sliders', 'smartphone-charging', 'smartphone', 'smile', 'snowflake', 'sort-asc', 'sort-desc', 'speaker', 'sprout', 'square', 'star-half', 'lucide-star', 'stop-circle', 'stretch-horizontal', 'stretch-vertical', 'strikethrough', 'subscript', 'sun', 'sunrise', 'sunset', 'superscript', 'swiss-franc', 'switch-camera', 'table', 'tablet', 'tag', 'target', 'tent', 'terminal-square', 'terminal', 'text-cursor-input', 'text-cursor', 'thermometer-snowflake', 'thermometer-sun', 'thermometer', 'thumbs-down', 'thumbs-up', 'ticket', 'timer-off', 'timer-reset', 'timer', 'toggle-left', 'toggle-right', 'tornado', 'trash-2', 'lucide-trash', 'trello', 'trending-down', 'trending-up', 'triangle', 'truck', 'tv-2', 'tv', 'twitch', 'twitter', 'type', 'umbrella', 'underline', 'undo', 'unlink-2', 'unlink', 'unlock', 'upload-cloud', 'upload', 'user-check', 'user-minus', 'user-plus', 'user-x', 'user', 'users', 'verified', 'vibrate', 'video-off', 'video', 'view', 'voicemail', 'volume-1', 'volume-2', 'volume-x', 'volume', 'wallet', 'wand', 'watch', 'waves', 'webcam', 'wifi-off', 'wifi', 'wind', 'wrap-text', 'wrench', 'x-circle', 'x-octagon', 'x-square', 'x', 'youtube', 'zap-off', 'zap', 'zoom-in', 'zoom-out', 'search-large', 'lucide-search']; +export class PropertyMappingValidationError extends Error { + constructor(message: string) { + super(message); + } +} + +export class PropertyMappingNameConflictError extends Error { + constructor(message: string) { + super(message); + } +}