Skip to content

Commit

Permalink
add a basic test, fix some bugs in runtime
Browse files Browse the repository at this point in the history
  • Loading branch information
rjwebb committed Jan 22, 2025
1 parent d1935cd commit 87d2796
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 7 deletions.
2 changes: 1 addition & 1 deletion packages/core/src/Canvas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { logger } from "@libp2p/logger"
import type pg from "pg"

import { Signature, Action, Session, Message, Snapshot, SessionSigner, SignerCache } from "@canvas-js/interfaces"
import { AbstractModelDB, Model, ModelSchema, Effect } from "@canvas-js/modeldb"
import { AbstractModelDB, Model, ModelSchema, Effect, ContractModelSchema } from "@canvas-js/modeldb"
import { SIWESigner } from "@canvas-js/chain-ethereum"
import { AbstractGossipLog, GossipLogEvents, SignedMessage } from "@canvas-js/gossiplog"
import type { ServiceMap, NetworkConfig } from "@canvas-js/gossiplog/libp2p"
Expand Down
4 changes: 3 additions & 1 deletion packages/core/src/runtime/AbstractRuntime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,8 @@ export abstract class AbstractRuntime {
// create the two tables
// operations
outputSchema[`${modelName}:operations`] = {
$primary: "record_id/message_id",
$primary: "operation_id",
operation_id: "string",
record_id: "string",
message_id: "string",
operations: "json",
Expand Down Expand Up @@ -321,6 +322,7 @@ export abstract class AbstractRuntime {
operation: "set",
value: {
record_id: key,
operation_id: `${key}/${executionContext.id}`,
message_id: executionContext.id,
operations,
},
Expand Down
10 changes: 10 additions & 0 deletions packages/core/src/runtime/FunctionRuntime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,10 @@ export class FunctionRuntime<ModelsT extends ModelSchema> extends AbstractRuntim
},
yjsInsert: async (model: string, key: string, index: number, content: string) => {
assert(this.#context !== null, "expected this.#context !== null")

if (this.#context.operations[model] === undefined) {
this.#context.operations[model] = {}
}
if (this.#context.operations[model][key] === undefined) {
this.#context.operations[model][key] = []
}
Expand All @@ -224,6 +228,9 @@ export class FunctionRuntime<ModelsT extends ModelSchema> extends AbstractRuntim
},
yjsDelete: async (model: string, key: string, index: number, length: number) => {
assert(this.#context !== null, "expected this.#context !== null")
if (this.#context.operations[model] === undefined) {
this.#context.operations[model] = {}
}
if (this.#context.operations[model][key] === undefined) {
this.#context.operations[model][key] = []
}
Expand All @@ -241,6 +248,9 @@ export class FunctionRuntime<ModelsT extends ModelSchema> extends AbstractRuntim
formattingAttributes: Record<string, string>,
) => {
assert(this.#context !== null, "expected this.#context !== null")
if (this.#context.operations[model] === undefined) {
this.#context.operations[model] = {}
}
if (this.#context.operations[model][key] === undefined) {
this.#context.operations[model][key] = []
}
Expand Down
43 changes: 38 additions & 5 deletions packages/core/test/canvas.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,10 +188,10 @@ test("accept a manually encoded session/action with a legacy-style object arg",
contract: {
actions: {
createMessage(db, arg) {
t.deepEqual(arg, { objectArg: '1' })
}
t.deepEqual(arg, { objectArg: "1" })
},
},
models: {}
models: {},
},
topic: "com.example.app",
reset: true,
Expand Down Expand Up @@ -219,8 +219,8 @@ test("accept a manually encoded session/action with a legacy-style object arg",
type: "action",
did: sessionMessage.payload.did,
name: "createMessage",
args: { objectArg: '1' },
context: { timestamp: 0 }
args: { objectArg: "1" },
context: { timestamp: 0 },
},
}
const actionSignature = await session.signer.sign(actionMessage)
Expand Down Expand Up @@ -499,3 +499,36 @@ test("open custom modeldb tables", async (t) => {
await app.db.set("widgets", { id, name: "foobar" })
t.deepEqual(await app.db.get("widgets", id), { id, name: "foobar" })
})

test("create a contract with a yjs text table", async (t) => {
const app = await Canvas.initialize({
contract: {
models: {
// @ts-ignore
posts: { id: "primary", content: "yjs-text" },
},
actions: {
createPost: (db, { key, index, content }: { key: string; index: number; content: string }) => {
db.yjsInsert("posts", key, index, content)
},
},
},

topic: "com.example.app",
schema: { widgets: { id: "primary", name: "string" } },
})

t.teardown(() => app.stop())

await app.actions.createPost({ key: "post_1", index: 0, content: "hello world" })

const operations = await app.db.query("posts:operations")
const state = await app.db.query("posts:state")

t.is(operations.length, 1)
t.is(state.length, 1)

t.is(operations[0].record_id, "post_1")
t.is(state[0].id, "post_1")
t.is(state[0].content[0].insert, "hello world")
})
1 change: 1 addition & 0 deletions packages/modeldb/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export type PropertyType =
export type IndexInit = string

export type ModelSchema = Record<string, { $indexes?: IndexInit[]; $primary?: string } | Record<string, PropertyType>>
export type ContractModelSchema = { [key: string]: "yjs-text" }

// These are more structured representations of the schema defined by ModelSchema that are easier
// to work with at runtime
Expand Down

0 comments on commit 87d2796

Please sign in to comment.