UNPKG

envio

Version:

A latency and sync speed optimized, developer friendly blockchain data indexer.

264 lines (238 loc) • 9.82 kB
// 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 */