2021-06-03 03:36:25 +00:00
|
|
|
import {collect} from '../collection/Collection'
|
|
|
|
import {InvalidJSONStateError, JSONState, Rehydratable} from './Rehydratable'
|
|
|
|
import {Pipe} from './Pipe'
|
2021-06-02 01:59:40 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* A class for building and working with messages grouped by keys.
|
|
|
|
*/
|
|
|
|
export class Messages implements Rehydratable {
|
|
|
|
protected messages: {[key: string]: string[]} = {}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param [allMessages] an initial array of messages to put in the "all" key
|
|
|
|
*/
|
|
|
|
constructor(allMessages?: string[]) {
|
|
|
|
if ( allMessages ) {
|
|
|
|
this.messages.all = allMessages
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** All group keys of messages. */
|
|
|
|
public keys(): string[] {
|
|
|
|
return Object.keys(this.messages)
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Add a message to a group. */
|
|
|
|
public put(key: string, message: string): this {
|
|
|
|
if ( !this.messages[key] ) {
|
|
|
|
this.messages[key] = []
|
|
|
|
}
|
|
|
|
|
|
|
|
this.messages[key].push(message)
|
|
|
|
return this
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Returns true if the given group has the message. */
|
|
|
|
public has(key: string, message: string): boolean {
|
2021-06-03 03:36:25 +00:00
|
|
|
return Boolean(this.messages[key]?.includes(message))
|
2021-06-02 01:59:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns true if any messages are found.
|
|
|
|
* @param [forKeys] if provided, only search the given keys
|
|
|
|
*/
|
2021-06-03 03:36:25 +00:00
|
|
|
public any(forKeys?: string[]): boolean {
|
2021-06-02 01:59:40 +00:00
|
|
|
if ( forKeys ) {
|
|
|
|
return forKeys.map(key => this.messages[key])
|
|
|
|
.filter(Boolean)
|
|
|
|
.some((bag: string[]) => bag.length)
|
|
|
|
}
|
|
|
|
|
|
|
|
return Object.values(this.messages).some((bag: string[]) => bag.length)
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the first message.
|
|
|
|
* @param [forKey] if provided, only search the given key
|
|
|
|
*/
|
2021-06-03 03:36:25 +00:00
|
|
|
public first(forKey?: string): string | undefined {
|
|
|
|
if ( !forKey ) {
|
|
|
|
forKey = Object.keys(this.messages)[0]
|
|
|
|
}
|
|
|
|
|
2021-06-02 01:59:40 +00:00
|
|
|
if ( forKey && this.messages[forKey].length ) {
|
|
|
|
return this.messages[forKey][0]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return all messages in a flat array.
|
|
|
|
* @param [forKey] if provided, only search the given key
|
|
|
|
*/
|
2021-06-03 03:36:25 +00:00
|
|
|
public all(forKey?: string): string[] {
|
2021-06-02 01:59:40 +00:00
|
|
|
if ( forKey ) {
|
|
|
|
return this.messages[forKey] || []
|
|
|
|
}
|
|
|
|
|
2021-06-03 03:36:25 +00:00
|
|
|
return collect<string[]>(Object.values(this.messages)).collapse()
|
|
|
|
.all() as string[]
|
2021-06-02 01:59:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Flat array of only distinct messages.
|
|
|
|
* @param [forKey] if provided, only search the given key
|
|
|
|
*/
|
2021-06-03 03:36:25 +00:00
|
|
|
public unique(forKey?: string): string[] {
|
|
|
|
return collect<string>(this.all(forKey)).unique<string>()
|
|
|
|
.all()
|
2021-06-02 01:59:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the total number of messages.
|
|
|
|
* @param [forKey] if provided, only search the given key
|
|
|
|
*/
|
|
|
|
public count(forKey?: string): number {
|
|
|
|
return this.all(forKey).length
|
|
|
|
}
|
|
|
|
|
|
|
|
async dehydrate(): Promise<JSONState> {
|
|
|
|
return this.messages
|
|
|
|
}
|
|
|
|
|
|
|
|
rehydrate(state: JSONState): void {
|
|
|
|
if ( typeof state === 'object' && !Array.isArray(state) ) {
|
|
|
|
let all = true
|
|
|
|
for ( const key in state ) {
|
2021-06-03 03:36:25 +00:00
|
|
|
if ( !Object.prototype.hasOwnProperty.call(state, key) ) {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2021-06-02 01:59:40 +00:00
|
|
|
const set = state[key]
|
|
|
|
if ( !(Array.isArray(set) && set.every(x => typeof x === 'string')) ) {
|
2021-06-03 03:36:25 +00:00
|
|
|
all = false
|
|
|
|
break
|
2021-06-02 01:59:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( all ) {
|
2021-06-03 03:36:25 +00:00
|
|
|
this.messages = state as any
|
2021-06-02 01:59:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-03 03:36:25 +00:00
|
|
|
throw new InvalidJSONStateError('Invalid message state object.', { state })
|
2021-06-02 01:59:40 +00:00
|
|
|
}
|
|
|
|
|
2021-06-03 03:36:25 +00:00
|
|
|
toJSON(): {[key: string]: string[]} {
|
2021-06-02 01:59:40 +00:00
|
|
|
return this.messages
|
|
|
|
}
|
|
|
|
|
2021-06-03 03:36:25 +00:00
|
|
|
toString(): string {
|
|
|
|
return JSON.stringify(this.toJSON())
|
2021-06-02 01:59:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get a new Pipe object wrapping this instance.
|
|
|
|
*/
|
|
|
|
pipe(): Pipe<Messages> {
|
|
|
|
return Pipe.wrap<Messages>(this)
|
|
|
|
}
|
|
|
|
}
|