@sphereon/did-auth-siop
Version:
Self Issued OpenID V2 (SIOPv2) and OpenID 4 Verifiable Presentations (OID4VP)
128 lines (111 loc) • 5.53 kB
text/typescript
import Tags from 'language-tags'
import { SIOPErrors } from '../types'
import { isStringNullOrEmpty } from './ObjectUtils'
export class LanguageTagUtils {
private static readonly LANGUAGE_TAG_SEPARATOR = '#'
/**
* It will give back a fields which are language tag enabled. i.e. all fields with the fields names containing
* language tags e.g. fieldName#nl-NL
*
* @param source is the object from which the language enabled fields and their values will be extracted.
*/
static getAllLanguageTaggedProperties(source: object): Map<string, string> {
return this.getLanguageTaggedPropertiesMapped(source, new Map())
}
/**
* It will give back a fields which are language tag enabled and are listed in the required fields.
*
* @param source is the object from which the language enabled fields and their values will be extracted.
* @param requiredFieldNames the fields which are supposed to be language enabled. These are the only fields which should be returned.
*/
static getLanguageTaggedProperties(source: object, requiredFieldNames: Array<string>): Map<string, string> {
const languageTagEnabledFieldsNamesMapping: Map<string, string> = new Map<string, string>()
requiredFieldNames.forEach((value) => languageTagEnabledFieldsNamesMapping.set(value, value))
const languageTaggedPropertiesMapped = this.getLanguageTaggedPropertiesMapped(source, languageTagEnabledFieldsNamesMapping)
return languageTaggedPropertiesMapped
}
/**
* It will give back a fields which are language tag enabled and are mapped in the required fields.
*
* @param source is the object from which the language enabled fields and their values will be extracted.
* @param enabledFieldNamesMapping the fields which are supposed to be language enabled. These are the only fields which should be returned. And
* the fields names will be transformed as per the mapping provided.
*/
static getLanguageTaggedPropertiesMapped(source: object, enabledFieldNamesMapping: Map<string, string>): Map<string, string> {
// this.assertSourceIsWorthChecking(source)
this.assertValidTargetFieldNames(enabledFieldNamesMapping)
const discoveredLanguageTaggedFields: Map<string, string> = new Map<string, string>()
if (source !== null && source !== undefined) {
Object.entries(source).forEach(([key, value]) => {
const languageTagSeparatorIndexInKey: number = key.indexOf(this.LANGUAGE_TAG_SEPARATOR)
if (this.isFieldLanguageTagged(languageTagSeparatorIndexInKey)) {
this.extractLanguageTaggedField(
key,
value as string,
languageTagSeparatorIndexInKey,
enabledFieldNamesMapping,
discoveredLanguageTaggedFields,
)
}
})
}
return discoveredLanguageTaggedFields
}
private static extractLanguageTaggedField(
key: string,
value: string,
languageTagSeparatorIndexInKey: number,
languageTagEnabledFieldsNamesMapping: Map<string, string>,
languageTaggedFields: Map<string, string>,
): void {
const fieldName = this.getFieldName(key, languageTagSeparatorIndexInKey)
const languageTag = this.getLanguageTag(key, languageTagSeparatorIndexInKey)
if (Tags.check(languageTag)) {
if (languageTagEnabledFieldsNamesMapping?.size) {
if (languageTagEnabledFieldsNamesMapping.has(fieldName)) {
languageTaggedFields.set(this.getMappedFieldName(languageTagEnabledFieldsNamesMapping, fieldName, languageTag), value)
}
} else {
languageTaggedFields.set(key, value)
}
}
}
private static getMappedFieldName(languageTagEnabledFieldsNamesMapping: Map<string, string>, fieldName: string, languageTag: string): string {
return languageTagEnabledFieldsNamesMapping.get(fieldName) + this.LANGUAGE_TAG_SEPARATOR + languageTag
}
private static getLanguageTag(key: string, languageTagSeparatorIndex: number): string {
return key.substring(languageTagSeparatorIndex + 1)
}
private static getFieldName(key: string, languageTagSeparatorIndex: number): string {
return key.substring(0, languageTagSeparatorIndex)
}
/***
* This function checks about the field to be language-tagged.
*
* @param languageTagSeparatorIndex
* @private
*/
private static isFieldLanguageTagged(languageTagSeparatorIndex: number): boolean {
return languageTagSeparatorIndex > 0
}
private static assertValidTargetFieldNames(languageTagEnabledFieldsNamesMapping: Map<string, string>): void {
if (languageTagEnabledFieldsNamesMapping) {
if (languageTagEnabledFieldsNamesMapping.size) {
for (const entry of languageTagEnabledFieldsNamesMapping.entries()) {
const key = entry[0]
const value = entry[1]
if (isStringNullOrEmpty(key) || isStringNullOrEmpty(value)) {
throw new Error(SIOPErrors.BAD_PARAMS + '. languageTagEnabledFieldsName must be non-null or non-empty')
}
}
} /* else { this would fail test "return no lingually tagged fields if there are no lingually tagged fields in the source object"
throw new Error(SIOPErrors.BAD_PARAMS + ' LanguageTagEnabledFieldsNamesMapping must be non-null or non-empty');
}*/
}
}
/* private static assertSourceIsWorthChecking(source: unknown): void {
if (!source) {
throw new Error(SIOPErrors.BAD_PARAMS + ' Source must be non-null i.e. not-initialized.')
}
}*/
}