diff --git a/packages/sdk/CHANGELOG.md b/packages/sdk/CHANGELOG.md index 7d06b6fb..0b3ba422 100644 --- a/packages/sdk/CHANGELOG.md +++ b/packages/sdk/CHANGELOG.md @@ -7,20 +7,11 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline **Note:** Version bump only for package @dojoengine/sdk - - - - # [1.0.0-alpha.30](https://github.com/dojoengine/sdk/compare/v1.0.0-alpha.29...v1.0.0-alpha.30) (2024-11-09) - ### Features -* docs ([1bf47fa](https://github.com/dojoengine/sdk/commit/1bf47fae3afef5ab7f02f9ed288141e735ab2788)) - - - - +- docs ([1bf47fa](https://github.com/dojoengine/sdk/commit/1bf47fae3afef5ab7f02f9ed288141e735ab2788)) # [1.0.0-alpha.29](https://github.com/dojoengine/sdk/compare/v1.0.0-alpha.28...v1.0.0-alpha.29) (2024-11-08) diff --git a/packages/sdk/src/__example__/index.ts b/packages/sdk/src/__example__/index.ts index 0270132d..e93d25bc 100644 --- a/packages/sdk/src/__example__/index.ts +++ b/packages/sdk/src/__example__/index.ts @@ -1,7 +1,7 @@ // EXAMPLE FOR NOW import * as torii from "@dojoengine/torii-client"; -import { init } from ".."; +import { init, QueryBuilder } from ".."; import { SchemaType } from "../types"; export interface PlayerModel { @@ -111,73 +111,49 @@ async function exampleUsage() { invalidMessage // TypeScript Error ); - db.subscribeEntityQuery( - { - world: { - player: { - $: { - where: { - name: { $is: "Alice" }, - score: { $is: 10 }, - }, - }, - }, - }, - }, - (resp) => { + const query = new QueryBuilder().namespace("world", (n) => + n.entity("player", (e) => e.eq("name", "Alice")) + ); + + db.subscribeEntityQuery(query.build(), (resp) => { + if (resp.error) { + console.error( + "Error querying todos and goals:", + resp.error.message + ); + return; + } + if (resp.data) { + console.log( + "Queried todos and goals:", + resp.data.map((a) => a.models.world) + ); + } + }); + // Example usage of getEntities with where clause + try { + const eq = new QueryBuilder().namespace("world", (n) => + n + .entity("item", (e) => + e.eq("type", "sword").lt("durability", 5) + ) + .entity("game", (e) => e.eq("status", "completed")) + ); + const entities = await db.getEntities(eq.build(), (resp) => { if (resp.error) { console.error( - "Error querying todos and goals:", + "Error querying completed important todos:", resp.error.message ); return; } if (resp.data) { console.log( - "Queried todos and goals:", - resp.data.map((a) => a.models.world) + "Completed important todos:", + resp.data.map((a) => a.models) ); } - } - ); - // Example usage of getEntities with where clause - try { - const entities = await db.getEntities( - { - world: { - item: { - $: { - where: { - type: { $eq: "sword" }, - durability: { $lt: 5 }, - }, - }, - }, - game: { - $: { - where: { - status: { $eq: "completed" }, - }, - }, - }, - }, - }, - (resp) => { - if (resp.error) { - console.error( - "Error querying completed important todos:", - resp.error.message - ); - return; - } - if (resp.data) { - console.log( - "Completed important todos:", - resp.data.map((a) => a.models) - ); - } - } - ); + }); console.log("Queried entities:", entities); } catch (error) { console.error("Error querying entities:", error); diff --git a/packages/sdk/src/__tests__/queryBuilder.test.ts b/packages/sdk/src/__tests__/queryBuilder.test.ts index e69b8a6a..6724fec7 100644 --- a/packages/sdk/src/__tests__/queryBuilder.test.ts +++ b/packages/sdk/src/__tests__/queryBuilder.test.ts @@ -1,5 +1,6 @@ import { describe, expect, it } from "vitest"; import { QueryBuilder } from "../queryBuilder"; +import { MockSchemaType } from "../__example__/index"; describe("QueryBuilder", () => { it("should be implemented", () => { @@ -8,9 +9,9 @@ describe("QueryBuilder", () => { }); it("should work with example", () => { - const query = new QueryBuilder() + const query = new QueryBuilder() .namespace("world", (n) => - n.entity("player", (e) => e.eq("id", "1").eq("name", "Alice")) + n.entity("test", (e) => e.eq("id", "1").eq("name", "Alice")) ) .namespace("universe", (n) => n.entity("galaxy", (e) => e.is("name", "Milky Way")) diff --git a/packages/sdk/src/queryBuilder.ts b/packages/sdk/src/queryBuilder.ts index 52c3789b..297e0c7a 100644 --- a/packages/sdk/src/queryBuilder.ts +++ b/packages/sdk/src/queryBuilder.ts @@ -1,4 +1,12 @@ -import { QueryType, SchemaType } from "./types"; +import { QueryType, SchemaType, SubscriptionQueryType } from "./types"; + +type NestedKeyOf = { + [Key in keyof ObjectType & + (string | number)]: ObjectType[Key] extends object + ? `${Key}` | `${Key}.${NestedKeyOf}` + : `${Key}`; +}[keyof ObjectType & (string | number)]; + export class QueryBuilder { namespaces: Map>; @@ -7,16 +15,16 @@ export class QueryBuilder { } public namespace( - name: string, + name: keyof T, cb: (ns: Namespace) => void ): Namespace { - const ns = new Namespace(this, name); - this.namespaces.set(name, ns); + const ns = new Namespace(this); + this.namespaces.set(name as string, ns); cb(ns); return ns; } - public build(): QueryType { + public build(): SubscriptionQueryType { const qt: Record< string, Record< @@ -43,25 +51,22 @@ export class QueryBuilder { }; } } - return qt as QueryType; + return qt as SubscriptionQueryType; } } class Namespace { entities: Map>; - constructor( - private parent: QueryBuilder, - private name: string - ) { + constructor(private parent: QueryBuilder) { this.entities = new Map>(); } public entity( - name: string, + name: NestedKeyOf, cb: (entity: QueryEntity) => void ): QueryEntity { - const entity = new QueryEntity(this, name); + const entity = new QueryEntity(this); this.entities.set(name, entity); cb(entity); return entity; @@ -71,53 +76,56 @@ class Namespace { return this.parent.namespace(ns, cb); } - public build(): QueryType { + public build(): SubscriptionQueryType { return this.parent.build(); } } class QueryEntity { - constraints: Map>; + constraints: Map; - constructor( - private parent: Namespace, - private name: string - ) { - this.constraints = new Map>(); + constructor(private parent: Namespace) { + this.constraints = new Map(); + } + public entity( + name: NestedKeyOf, + cb: (entity: QueryEntity) => void + ): QueryEntity { + return this.parent.entity(name, cb); } public is(field: string, value: any): QueryEntity { - this.constraints.set(field, new Constraint(this, Operator.is, value)); + this.constraints.set(field, new Constraint(Operator.is, value)); return this; } public eq(field: string, value: any): QueryEntity { - this.constraints.set(field, new Constraint(this, Operator.eq, value)); + this.constraints.set(field, new Constraint(Operator.eq, value)); return this; } public neq(field: string, value: any): QueryEntity { - this.constraints.set(field, new Constraint(this, Operator.neq, value)); + this.constraints.set(field, new Constraint(Operator.neq, value)); return this; } public gt(field: string, value: any): QueryEntity { - this.constraints.set(field, new Constraint(this, Operator.gt, value)); + this.constraints.set(field, new Constraint(Operator.gt, value)); return this; } public gte(field: string, value: any): QueryEntity { - this.constraints.set(field, new Constraint(this, Operator.gte, value)); + this.constraints.set(field, new Constraint(Operator.gte, value)); return this; } public lt(field: string, value: any): QueryEntity { - this.constraints.set(field, new Constraint(this, Operator.lt, value)); + this.constraints.set(field, new Constraint(Operator.lt, value)); return this; } public lte(field: string, value: any): QueryEntity { - this.constraints.set(field, new Constraint(this, Operator.lte, value)); + this.constraints.set(field, new Constraint(Operator.lte, value)); return this; } @@ -126,9 +134,8 @@ class QueryEntity { } } -class Constraint { +class Constraint { constructor( - private parent: QueryEntity, private _operator: Operator, private _value: any ) {}