envio
Version:
A latency and sync speed optimized, developer friendly blockchain data indexer.
264 lines (238 loc) • 9.82 kB
JavaScript
// Generated by ReScript, PLEASE EDIT WITH CARE
import * as Utils from "./Utils.res.mjs";
import * as Address from "./Address.res.mjs";
import * as Logging from "./Logging.res.mjs";
import * as ChainMap from "./ChainMap.res.mjs";
import * as Internal from "./Internal.res.mjs";
import * as LoadLayer from "./LoadLayer.res.mjs";
import * as EntityFilter from "./db/EntityFilter.res.mjs";
import * as ErrorHandling from "./ErrorHandling.res.mjs";
import * as InMemoryStore from "./InMemoryStore.res.mjs";
import * as InMemoryTable from "./InMemoryTable.res.mjs";
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
import * as S$RescriptSchema from "rescript-schema/src/S.res.mjs";
let paramsByThis = new WeakMap();
let effectContextPrototype = (Object.create(null));
Object.defineProperty(effectContextPrototype, "log", {
get: function () {
return Logging.getUserLogger(paramsByThis.get(this).item);
}
});
var EffectContext = function(params, defaultShouldCache, callEffect) {
paramsByThis.set(this, params);
this.effect = callEffect;
this.cache = defaultShouldCache;
};
EffectContext.prototype = effectContextPrototype;
;
function initEffect(params) {
let callEffect = (effect, input) => {
let effectContext = new EffectContext(params, effect.defaultShouldCache, callEffect);
let effectArgs_cacheKey = Utils.Hash.makeOrThrow(S$RescriptSchema.reverseConvertOrThrow(input, effect.input));
let effectArgs_checkpointId = params.checkpointId;
let effectArgs = {
input: input,
context: effectContext,
cacheKey: effectArgs_cacheKey,
checkpointId: effectArgs_checkpointId
};
return LoadLayer.loadEffect(params.loadManager, params.persistence, effect, effectArgs, params.inMemoryStore, params.isPreload, params.item);
};
return callEffect;
}
function getWhereHandler(params, filter) {
let entityConfig = params.entityConfig;
let filters = EntityFilter.parseGetWhereOrThrow(filter, entityConfig.name, entityConfig.table);
if (filters.length !== 1) {
return Promise.all(filters.map(filter => LoadLayer.loadByFilter(params.loadManager, params.persistence, entityConfig, params.inMemoryStore, params.isPreload, params.item, filter))).then(results => results.flat());
} else {
return LoadLayer.loadByFilter(params.loadManager, params.persistence, entityConfig, params.inMemoryStore, params.isPreload, params.item, filters[0]);
}
}
function noopSet(_entity) {
}
function noopDeleteUnsafe(_entityId) {
}
function throwClickHouseReadOnly(entityConfig, op) {
return Stdlib_JsError.throwWithMessage(`context.` + entityConfig.name + `.` + op + `() is unavailable: ClickHouse storage is currently write-only. Follow Envio releases to be notified when ClickHouse supports both reads and writes from handlers.`);
}
let entityTraps_get = (params, prop) => {
let isClickHouseOnly = !params.entityConfig.storage.postgres;
let set = params.isPreload ? noopSet : entity => InMemoryTable.Entity.set(InMemoryStore.getInMemTable(params.inMemoryStore, params.entityConfig), params.inMemoryStore.committedCheckpointId, {
type: "SET",
entityId: entity.id,
entity: entity,
checkpointId: params.checkpointId
});
switch (prop) {
case "deleteUnsafe" :
if (params.isPreload) {
return noopDeleteUnsafe;
} else {
return entityId => InMemoryTable.Entity.set(InMemoryStore.getInMemTable(params.inMemoryStore, params.entityConfig), params.inMemoryStore.committedCheckpointId, {
type: "DELETE",
entityId: entityId,
checkpointId: params.checkpointId
});
}
case "get" :
if (isClickHouseOnly) {
return _entityId => throwClickHouseReadOnly(params.entityConfig, "get");
} else {
return entityId => LoadLayer.loadById(params.loadManager, params.persistence, params.entityConfig, params.inMemoryStore, params.isPreload, params.item, entityId);
}
case "getOrCreate" :
if (isClickHouseOnly) {
return _entity => throwClickHouseReadOnly(params.entityConfig, "getOrCreate");
} else {
return entity => LoadLayer.loadById(params.loadManager, params.persistence, params.entityConfig, params.inMemoryStore, params.isPreload, params.item, entity.id).then(storageEntity => {
if (storageEntity !== undefined) {
return storageEntity;
} else {
set(entity);
return entity;
}
});
}
case "getOrThrow" :
if (isClickHouseOnly) {
return (_entityId, param) => throwClickHouseReadOnly(params.entityConfig, "getOrThrow");
} else {
return (entityId, message) => LoadLayer.loadById(params.loadManager, params.persistence, params.entityConfig, params.inMemoryStore, params.isPreload, params.item, entityId).then(entity => {
if (entity !== undefined) {
return entity;
} else {
return Stdlib_JsError.throwWithMessage(Stdlib_Option.getOr(message, `Entity '` + params.entityConfig.name + `' with ID '` + entityId + `' is expected to exist.`));
}
});
}
case "getWhere" :
if (isClickHouseOnly) {
return _filter => throwClickHouseReadOnly(params.entityConfig, "getWhere");
} else {
return filter => getWhereHandler(params, filter);
}
case "set" :
return set;
default:
return Stdlib_JsError.throwWithMessage(`Invalid context.` + params.entityConfig.name + `.` + prop + ` operation.`);
}
};
let entityTraps = {
get: entityTraps_get
};
let handlerTraps_get = (params, prop) => {
if (params.isResolved) {
ErrorHandling.mkLogAndRaise(Logging.getItemLogger(params.item), undefined, new Error(`Impossible to access context.` + prop + ` after the handler is resolved. Make sure you didn't miss an await in the handler.`));
}
switch (prop) {
case "chain" :
let chainId = Internal.getItemChainId(params.item);
return params.chains[chainId];
case "effect" :
return initEffect(params);
case "isPreload" :
return params.isPreload;
case "log" :
if (params.isPreload) {
return Logging.noopLogger;
} else {
return Logging.getUserLogger(params.item);
}
default:
let entityConfig = params.config.userEntitiesByName[prop];
if (entityConfig !== undefined) {
return new Proxy({
item: params.item,
checkpointId: params.checkpointId,
inMemoryStore: params.inMemoryStore,
loadManager: params.loadManager,
persistence: params.persistence,
isPreload: params.isPreload,
chains: params.chains,
config: params.config,
isResolved: params.isResolved,
entityConfig: entityConfig
}, entityTraps);
} else {
return Stdlib_JsError.throwWithMessage(`Invalid context access by '` + prop + `' property. ` + EntityFilter.codegenHelpMessage);
}
}
};
let handlerTraps = {
get: handlerTraps_get
};
function getHandlerContext(params) {
return new Proxy(params, handlerTraps);
}
function makeAddFunction(params, contractName) {
return contractAddress => {
if (params.isResolved) {
ErrorHandling.mkLogAndRaise(Logging.getItemLogger(params.item), undefined, new Error(`Impossible to access context.chain after the contract register is resolved. Make sure you didn't miss an await in the handler.`));
}
let validatedAddress = params.config.ecosystem.name === "evm" ? (
params.config.lowercaseAddresses ? Address.Evm.fromAddressLowercaseOrThrow(contractAddress) : Address.Evm.fromAddressOrThrow(contractAddress)
) : contractAddress;
params.onRegister(params.item, validatedAddress, contractName);
};
}
let contractRegisterChainTraps_get = (params, prop) => {
if (prop === "id") {
return params.item.chain;
}
let isValidContract = ChainMap.values(params.config.chainMap).some(chain => chain.contracts.some(c => c.name === prop));
if (isValidContract) {
return {
add: makeAddFunction(params, prop)
};
} else {
return Stdlib_JsError.throwWithMessage(`Invalid contract name '` + prop + `' on context.chain. ` + EntityFilter.codegenHelpMessage);
}
};
let contractRegisterChainTraps = {
get: contractRegisterChainTraps_get
};
let contractRegisterTraps_get = (params, prop) => {
if (params.isResolved) {
ErrorHandling.mkLogAndRaise(Logging.getItemLogger(params.item), undefined, new Error(`Impossible to access context.` + prop + ` after the contract register is resolved. Make sure you didn't miss an await in the handler.`));
}
switch (prop) {
case "chain" :
return new Proxy(params, contractRegisterChainTraps);
case "log" :
return Logging.getUserLogger(params.item);
default:
return Stdlib_JsError.throwWithMessage(`Invalid context access by '` + prop + `' property. Use context.chain.ContractName.add(address) to register contracts. ` + EntityFilter.codegenHelpMessage);
}
};
let contractRegisterTraps = {
get: contractRegisterTraps_get
};
function getContractRegisterContext(params) {
return new Proxy(params, contractRegisterTraps);
}
function getContractRegisterArgs(params) {
return {
event: params.item.event,
context: new Proxy(params, contractRegisterTraps)
};
}
export {
paramsByThis,
effectContextPrototype,
initEffect,
getWhereHandler,
noopSet,
noopDeleteUnsafe,
throwClickHouseReadOnly,
entityTraps,
handlerTraps,
getHandlerContext,
makeAddFunction,
contractRegisterChainTraps,
contractRegisterTraps,
getContractRegisterContext,
getContractRegisterArgs,
}
/* paramsByThis Not a pure module */