diff --git a/package.json b/package.json index 5e8f533c..d8d748f7 100644 --- a/package.json +++ b/package.json @@ -1,25 +1,25 @@ { - "name": "dojo.js", - "scripts": { - "build": "bash ./scripts/build-packages.sh", - "build-examples": "bash ./scripts/build-examples.sh", - "clean": "bash ./scripts/clean.sh", - "prettier-check": "npx prettier --check {packages,examples}", - "prettier": "npx prettier --write .", - "release": "pnpm build && pnpm prettier && npx lerna publish --no-private --force-publish", - "docs": "npx typedoc --out docs", - "prepare": "husky install" - }, - "devDependencies": { - "husky": "^9.1.6", - "lerna": "^8.1.5", - "prettier": "^3.3.3", - "tsup": "^8.1.0", - "typedoc": "^0.26.7", - "@typhonjs-typedoc/typedoc-theme-dmt": "^0.2.1", - "typedoc-plugin-coverage": "^3.3.0", - "@commitlint/cli": "^18.4.4", - "@commitlint/config-conventional": "^18.4.4", - "@ianvs/prettier-plugin-sort-imports": "^4.3.1" - } + "name": "dojo.js", + "scripts": { + "build": "bash ./scripts/build-packages.sh", + "build-examples": "bash ./scripts/build-examples.sh", + "clean": "bash ./scripts/clean.sh", + "prettier-check": "npx prettier --check {packages,examples}", + "prettier": "npx prettier --write .", + "release": "pnpm build && pnpm prettier && npx lerna publish --no-private --force-publish", + "docs": "npx typedoc --out docs", + "prepare": "husky install" + }, + "devDependencies": { + "husky": "^9.1.6", + "lerna": "^8.1.5", + "prettier": "^3.3.3", + "tsup": "^8.1.0", + "typedoc": "^0.26.7", + "@typhonjs-typedoc/typedoc-theme-dmt": "^0.2.1", + "typedoc-plugin-coverage": "^3.3.0", + "@commitlint/cli": "^18.4.4", + "@commitlint/config-conventional": "^18.4.4", + "@ianvs/prettier-plugin-sort-imports": "^4.3.1" + } } diff --git a/packages/state/src/recs/index.ts b/packages/state/src/recs/index.ts index 2c127cf7..6993c4d6 100644 --- a/packages/state/src/recs/index.ts +++ b/packages/state/src/recs/index.ts @@ -8,12 +8,12 @@ import { } from "@dojoengine/recs"; import { Clause, + Entities, EntityKeysClause, OrderBy, PatternMatching, ToriiClient, } from "@dojoengine/torii-client"; - import { convertValues } from "../utils"; /** @@ -144,12 +144,21 @@ export const getEntities = async ( orderBy: OrderBy[] = [], entityModels: string[] = [], limit: number = 100, - logging: boolean = false + logging: boolean = false, + { + dbConnection, + timestampCacheKey, + }: { dbConnection: IDBDatabase | undefined; timestampCacheKey: string } = { + dbConnection: undefined, + timestampCacheKey: "", + } ) => { if (logging) console.log("Starting getEntities"); let offset = 0; let continueFetching = true; + const time = dbConnection ? getCache(timestampCacheKey) : 0; + while (continueFetching) { const entities = await client.getEntities({ limit, @@ -158,11 +167,14 @@ export const getEntities = async ( order_by: orderBy, entity_models: entityModels, dont_include_hashed_keys: false, + internal_updated_at: time, }); - console.log("entities", entities); + if (dbConnection) { + await insertEntitiesInDB(dbConnection, entities); + } - if (logging) console.log(`Fetched ${entities} entities`); + if (logging) console.log(`Fetched entities`, entities); setEntities(entities, components, logging); @@ -172,6 +184,11 @@ export const getEntities = async ( offset += limit; } } + + if (dbConnection) { + const currentTime = Math.floor(Date.now() / 1000); + setCache(currentTime, timestampCacheKey); + } }; /** @@ -209,6 +226,7 @@ export const getEvents = async ( order_by: orderBy, entity_models: entityModels, dont_include_hashed_keys: false, + internal_updated_at: 0, }, historical ); @@ -284,6 +302,7 @@ export const getEntitiesQuery = async ( order_by: orderBy, entity_models: entityModels, dont_include_hashed_keys: false, + internal_updated_at: 0, }); while (continueFetching) { @@ -449,3 +468,53 @@ export const setEntities = async ( } } }; + +const setCache = (time: number, timestampCacheKey: string) => { + const timeString = Math.floor(time).toString(); + localStorage.setItem(timestampCacheKey, timeString); +}; + +const getCache = (timestampCacheKey: string) => { + return Number(localStorage.getItem(timestampCacheKey) || 0); +}; + +async function insertEntitiesInDB( + db: IDBDatabase, + entities: Entities +): Promise { + return new Promise((resolve, reject) => { + const transaction = db.transaction(["entities"], "readwrite"); + const store = transaction.objectStore("entities"); + + let completed = 0; + let error: Error | null = null; + + // Handle transaction completion + transaction.oncomplete = () => { + if (error) { + reject(error); + } else { + resolve(); + } + }; + + transaction.onerror = () => { + reject(transaction.error); + }; + + // Store each entity + for (const [entityId, data] of Object.entries(entities)) { + const entityData = { + id: entityId, + ...data, + }; + + const request = store.put(entityData); + completed++; + + request.onerror = () => { + error = request.error; + }; + } + }); +}