All files / src/storage/schema/entities EntityBase.ts

100% Statements 7/7
100% Branches 0/0
100% Functions 3/3
100% Lines 7/7

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145        57x       11340x                                                                                                                                       6144x 6144x                                                                                       57x 16x                           16x                
import { sdk, StorageProvider } from "../../../index.client";
 
export type EntityStorage = StorageProvider
 
export abstract class EntityBase<T> {
    api: T;
 
    constructor(api: T) {
        this.api = api;
    }
 
    /**
     * Standard property for entity database Id
     */
    abstract get id() : number
    
    /**
     * Name of derived entity class
     */
    abstract get entityName(): string
 
    /**
     * Schema table name of entity
     */
    abstract get entityTable(): string
 
    /**
     * On construction, an entity may decode properties of the `api` object,
     * such as JSON stringified objects.
     * 
     * The `updateApi` method must re-encode the current state of those decoded properties
     * into the `api` object.
     * 
     * Used by the `toApi` method to return an updated `api` object.
     */
    abstract updateApi(): void;
 
    /**
     * Tests for equality or 'merge' / 'convergent' equality if syncMap is provided.
     * 
     * 'convergent' equality must satisfy (A sync B) equals (B sync A)
     * 
     * @param ei 
     * @param syncMap 
     */
    abstract equals(ei: T, syncMap?: SyncMap) : boolean
    
    /**
     * Perform a 'merge' / 'convergent' equality migration of state
     * to this new local entity which was constructed
     * as a copy of the external object.
     * 
     * @param userId local userId 
     * @param syncMap 
     */
    abstract mergeNew(storage: EntityStorage, userId: number, syncMap: SyncMap, trx?: sdk.TrxToken) : Promise<void>
 
    /**
     * Perform a 'merge' / 'convergent' equality migration of state
     * from external `ei` to this existing local entity.
     * 
     * @param ei 
     * @param syncMap
     * @returns true iff entity state changed and was updated to storage
     */
    abstract mergeExisting(storage: EntityStorage, since: Date | undefined, ei: T, syncMap: SyncMap, trx?: sdk.TrxToken) : Promise<boolean>
 
    /**
     * An entity may decode properties of the underlying Api object on construction.
     * 
     * The `toApi` method forces an `updateApi` before returning the underlying,
     * now updated, Api object.
     * 
     * @returns The underlying Api object with any entity decoded properties updated.
     */
    toApi(): T {
        this.updateApi();
        return this.api;
    }
 
}
 
export interface EntitySyncMap {
    entityName: string
 
    /**
     * Maps foreign ids to local ids
     * Some entities don't have idMaps (CertificateField, TxLabelMap and OutputTagMap)
     */
    idMap: Record<number, number>
 
    /**
     * the maximum updated_at value seen for this entity over chunks received
     * during this udpate cycle.
     */
    maxUpdated_at?: Date
 
    /**
     * The cummulative count of items of this entity type received over all the `SyncChunk`s
     * since the `since` was last updated.
     * 
     * This is the `offset` value to use for the next SyncChunk request.
     */
    count: number
}
 
export interface SyncMap {
    provenTx: EntitySyncMap
    outputBasket: EntitySyncMap
    transaction: EntitySyncMap
    provenTxReq: EntitySyncMap
    txLabel: EntitySyncMap
    txLabelMap: EntitySyncMap
    output: EntitySyncMap
    outputTag: EntitySyncMap
    outputTagMap: EntitySyncMap
    certificate: EntitySyncMap
    certificateField: EntitySyncMap
    commission: EntitySyncMap
}
 
export function createSyncMap(): SyncMap {
    const r: SyncMap = {
        provenTx: { entityName: 'provenTx', idMap: {}, maxUpdated_at: undefined, count: 0 },
        outputBasket: { entityName: 'outputBasket', idMap: {}, maxUpdated_at: undefined, count: 0 },
        transaction: { entityName: 'transaction', idMap: {}, maxUpdated_at: undefined, count: 0 },
        provenTxReq: { entityName: 'provenTxReq', idMap: {}, maxUpdated_at: undefined, count: 0 },
        txLabel: { entityName: 'txLabel', idMap: {}, maxUpdated_at: undefined, count: 0 },
        txLabelMap: { entityName: 'txLabelMap', idMap: {}, maxUpdated_at: undefined, count: 0 },
        output: { entityName: 'output', idMap: {}, maxUpdated_at: undefined, count: 0 },
        outputTag: { entityName: 'outputTag', idMap: {}, maxUpdated_at: undefined, count: 0 },
        outputTagMap: { entityName: 'outputTagMap', idMap: {}, maxUpdated_at: undefined, count: 0 },
        certificate: { entityName: 'certificate', idMap: {}, maxUpdated_at: undefined, count: 0 },
        certificateField: { entityName: 'certificateField', idMap: {}, maxUpdated_at: undefined, count: 0 },
        commission: { entityName: 'commission', idMap: {}, maxUpdated_at: undefined, count: 0 },
    }
    return r
}
 
export interface SyncError {
   code: string
   description: string
   stack?: string
}