/*! * SAPUI5 * Copyright (c) 2025 SAP SE or an SAP affiliate company. All rights reserved. */ type CustomMakeSafeObjectFunction = (value: unknown, safeAssignmentObject: ObjectSafeAssignment) => unknown; export type Log = (msg: string) => void; // eslint-disable-next-line @typescript-eslint/no-unused-vars const defaultLog: Log = (msg: string) => {}; export interface Property { name: string | RegExp; safeAssigment?: SafeAssignment; } interface SafeAssignment { log: Log; makeSafe(obj: T): T; } export class StringSafeAssigment implements SafeAssignment { public log: Log; constructor(log: Log) { this.log = log ?? defaultLog; } makeSafe(obj: T): T { if (typeof obj === "string") { return obj; } this.log(`StringSafeAssignment replace '${obj}' by ''`); return "" as T; } } export class ObjectSafeAssignment implements SafeAssignment { public log: Log; private properties: Array = []; private customMakeSafe: CustomMakeSafeObjectFunction; constructor(opts: { log?: Log; makeSafe?: CustomMakeSafeObjectFunction; properties: Array; }) { this.log = opts.log ?? defaultLog; if (opts.makeSafe) { this.customMakeSafe = opts.makeSafe; } for (const property of opts.properties) { if (typeof property === "string") { this.properties.push({ name: property }); } else { this.properties.push(property); } } } public addProperty(property: Property) { this.properties.push(property); } private getProperty(propertyName: string): Property { for (const property of this.properties) { if (typeof property.name === "string") { if (property.name === propertyName) { return property; } } if (property.name instanceof RegExp) { if (property.name.test(propertyName)) { return property; } } } } public setProperty(targetObj: object, propertyName: string, propertyValue: unknown) { const property = this.getProperty(propertyName); if (!property) { this.log(`SafeAssigment remove property ${propertyName}`); return; } if (property.safeAssigment) { targetObj[propertyName] = property.safeAssigment.makeSafe(propertyValue); } else { if (!["number", "string", "boolean", "undefined", "bigint"].includes(typeof propertyValue)) { this.log( `SafeAssigment remove property because property is not a simple type ${propertyName}` ); return; } targetObj[propertyName] = propertyValue; } } public makeSafeProperties(obj: T): Partial { const result = {}; for (const propertyName in obj) { const propertyValue = obj[propertyName]; this.setProperty(result, propertyName, propertyValue); } return result; } public makeSafe(obj: T): T { if (this.customMakeSafe) { // custom implementation return this.customMakeSafe(obj, this) as T; } else { // default implementaion: iterate properties return this.makeSafeProperties(obj) as T; } } } export class ListSafeAssignment implements SafeAssignment { public log: Log; private listElementSafeAssigment: SafeAssignment; constructor(opts: { log?: Log; listElementSafeAssigment: SafeAssignment }) { this.log = opts.log ?? defaultLog; this.listElementSafeAssigment = opts.listElementSafeAssigment; } public makeSafe(list: T): T { if (!Array.isArray(list)) { this.log(`SafeAssigment replace ${list} by empty list`); return [] as T; } const result = []; for (const element of list as Array) { result.push(this.listElementSafeAssigment.makeSafe(element)); } return result as T; } }