import { FabricCrudContract } from "./crud-contract";
import { Model } from "@decaf-ts/decorator-validation";
import { MangoQuery } from "@decaf-ts/for-couchdb";
import { Context as Ctx, Transaction } from "fabric-contract-api";
import { Constructor } from "@decaf-ts/decoration";
/**
* @description CRUD contract variant that serializes/deserializes payloads
* @summary Exposes the same CRUD operations as FabricCrudContract but takes and returns JSON strings to facilitate simple client interactions.
* @template M - Model type handled by this contract
* @param {string} name - The contract name
* @param {Constructor<M>} clazz - The model constructor used to instantiate models from JSON
* @return {void}
* @class SerializedCrudContract
* @example
* const contract = new SerializedCrudContract<MyModel>('MyModelContract', MyModel);
* // Client submits JSON string payloads and receives JSON string responses
*/
export class SerializedCrudContract<
M extends Model,
> extends FabricCrudContract<M> {
constructor(name: string, clazz: Constructor<M>) {
super(name, clazz);
}
@Transaction()
override async create(ctx: Ctx, model: string): Promise<string> {
const { log } = await this.logCtx([ctx], this.create);
log.info(`Creating model: ${model}`);
const m = this.deserialize<M>(model);
log.info(`Model deserialized: ${JSON.stringify(m)}`);
return this.serialize((await super.create(ctx, m)) as M);
}
@Transaction(false)
override async read(ctx: Ctx, key: string): Promise<string> {
const { log } = await this.logCtx([ctx], this.read);
log.info(`Reading id: ${key}`);
return this.serialize((await super.read(ctx, key)) as M);
}
@Transaction()
override async update(ctx: Ctx, model: string): Promise<string> {
const { log } = await this.logCtx([ctx], this.update);
log.info(`Updating model: ${model}`);
return this.serialize((await super.update(ctx, model)) as M);
}
@Transaction()
override async delete(ctx: Ctx, key: string): Promise<string> {
const { log } = await this.logCtx([ctx], this.delete);
log.info(`Deleting id: ${key}`);
return this.serialize((await super.delete(ctx, key)) as M);
}
@Transaction()
override async deleteAll(ctx: Ctx, keys: string): Promise<string> {
const parsedKeys: string[] = JSON.parse(keys);
const { log } = await this.logCtx([ctx], this.deleteAll);
log.info(`deleting ${parsedKeys.length} entries from the table`);
return JSON.stringify(
((await super.deleteAll(ctx, parsedKeys)) as M[]).map(
(m) => this.serialize(m) as string
)
);
}
@Transaction(false)
override async readAll(ctx: Ctx, keys: string): Promise<string> {
const parsedKeys: string[] = JSON.parse(keys);
const { log } = await this.logCtx([ctx], this.readAll);
log.info(`reading ${parsedKeys.length} entries from the table`);
return JSON.stringify(
((await super.readAll(ctx, parsedKeys)) as M[]).map((m) =>
this.serialize(m)
)
);
}
@Transaction()
override async updateAll(ctx: Ctx, models: string): Promise<string> {
const { log } = await this.logCtx([ctx], this.updateAll);
const list: string[] = JSON.parse(models);
const modelList: M[] = list
.map((m) => this.deserialize(m))
.map((m) => new this.clazz(m));
log.info(`Updating ${modelList.length} entries to the table`);
return JSON.stringify(
((await super.updateAll(ctx, modelList)) as M[]).map(
(m) => this.serialize(m) as string
)
);
}
@Transaction(false)
override async raw(
context: Ctx,
rawInput: string,
docsOnly: boolean
): Promise<any> {
const { ctx } = await this.logCtx([context], this.raw);
const parsedInput: MangoQuery = JSON.parse(rawInput);
return super.raw(ctx, parsedInput, docsOnly);
}
@Transaction()
override async init(ctx: Ctx): Promise<void> {
await super.init(ctx);
}
@Transaction(false)
override async healthcheck(ctx: Ctx): Promise<string> {
//TODO: TRIM NOT WORKING CHECK LATER
return JSON.stringify(await super.healthcheck(ctx));
}
@Transaction()
override async createAll(context: Ctx, models: string): Promise<string> {
const { log } = await this.logCtx([context], this.createAll);
const list: string[] = JSON.parse(models);
const modelList: M[] = list
.map((m) => this.deserialize(m))
.map((m) => new this.clazz(m));
log.info(`Adding ${modelList.length} entries to the table`);
return JSON.stringify(
((await super.createAll(context, modelList)) as M[]).map(
(m) => this.serialize(m) as string
)
);
}
}
Source