0.12.1 • Published 9 months ago

@canvas-js/core v0.12.1

Weekly downloads
-
License
-
Repository
-
Last release
9 months ago

@canvas-js/core

A Canvas app replicates and executes a log of signed actions, sourced from GossipLog, with read/write access to a ModelDB database.

Use this package directly if you want fine-grained control over when an application is started/stopped. Otherwise, you can use useCanvas in @canvas-js/hooks, which has the same API, but handles initialization inside React for you.

Table of Contents

Installation

$ npm i @canvas-js/core

Usage

import { Canvas } from "@canvas-js/core"

const app = await Canvas.initialize({
  contract: {
    topic: "com.example.my-app",
    models: {
      posts: {
        id: "primary",
        user: "string",
        content: "string",
        updated_at: "integer",
      },
    },
    actions: {
      async createPost(db, { content }, { id, chain, address, timestamp }) {
        const user = [chain, address].join(":")
        await db.posts.set({ id, user, content, updated_at: timestamp })
      },
      async deletePost(db, { postId }, { chain, address }) {
        const post = await db.posts.get(postId)
        if (post === null) {
          return
        }

        const user = [chain, address].join(":")
        if (post.user !== user) {
          throw new Error("not authorized")
        }

        await db.posts.delete(postId)
      },
    },
  },
})

await app.actions.createPost({ content: "hello world!" })
const results = await app.db.query("posts", {})
// [
//   {
//     id: '09p5qn7affkhtbflscr663tet8ddeu41',
//     user: 'did:pkh:eip155:1:0x79c5158f81ebb0c2bcF877E9e1813aed2Eb652B7',
//     content: 'hello world!',
//     updated_at: 1698339861041
//   }
// ]

API

Contract types

import type { ModelSchema, ModelValue } from "@canvas-js/modeldb"
import type { Awaitable } from "@canvas-js/interfaces"

export type Contract = {
  topic: string
  models: ModelSchema
  actions: Record<string, ActionImplementationFunction | ActionImplementationObject>
}

export type ActionImplementationObject = {
  argsType?: { schema: string; name: string }
  apply: ActionImplementationFunction
}

export type ActionImplementationFunction = (
  db: Record<string, ModelAPI>,
  args: Args,
  context: ActionContext,
) => Awaitable<Result>

export type ModelAPI = {
  get: (key: string) => Promise<T | null>
  set: (value: ModelValue) => Promise<void>
  delete: (key: string) => Promise<void>
}

export type ActionContext = {
  id: string
  chain: string
  address: string
  blockhash: string | null
  timestamp: number
}

Canvas class

import { Signature, Action, Session, SessionSigner } from "@canvas-js/interfaces"
import { AbstractModelDB } from "@canvas-js/modeldb"

export interface NetworkConfig {
  offline?: boolean
  disablePing?: boolean
  /** array of local WebSocket multiaddrs, e.g. "/ip4/127.0.0.1/tcp/3000/ws" */
  listen?: string[]
  /** array of public WebSocket multiaddrs, e.g. "/dns4/myapp.com/tcp/443/wss" */
  announce?: string[]
  bootstrapList?: string[]
  minConnections?: number
  maxConnections?: number
  discoveryTopic?: string
  discoveryInterval?: number
  trackAllPeers?: boolean
  enableWebRTC?: boolean
}
export interface CanvasConfig<T extends Contract = Contract> extends NetworkConfig {
  contract: string | T
  signers?: SessionSigner[]
  /** data directory path (NodeJS only) */
  path?: string | null
  /** provide an existing libp2p instance instead of creating a new one */
  libp2p?: Libp2p<ServiceMap>
  runtimeMemoryLimit?: number
}

export interface CanvasEvents extends GossipLogEvents<Action | Session, unknown> {
  close: Event
  connect: CustomEvent<{
    peer: PeerId
  }>
  disconnect: CustomEvent<{
    peer: PeerId
  }>
  "connections:updated": CustomEvent<ConnectionsInfo>
  "presence:join": CustomEvent<PresenceInfo>
  "presence:leave": CustomEvent<PresenceInfo>
}

export declare class Canvas extends EventEmitter<CanvasEvents> {
  public static initialize(config: CanvasConfig): Promise<Canvas>

  public readonly topic: string
  public readonly signers: SessionSigner[]
  public readonly peerId: PeerId
  public readonly libp2p: Libp2p<ServiceMap> | null
  public readonly db: AbstractModelDB

  public readonly actions: Record<
    string,
    (
      args: any,
      options: { chain?: string; signer?: SessionSigner },
    ) => Promise<{ id: string; recipients: Promise<PeerId[]> }>
  >

  public close(): Promise<void>
  public start(): Promise<void>
  public stop(): Promise<void>

  public getMessage(id: string): Promise<[signature: Signature, message: Message<Action | Session>] | [null, null]>
  public getMessageStream(
    lowerBound?: { id: string; inclusive: boolean } | null,
    upperBound?: { id: string; inclusive: boolean } | null,
    options?: { reverse?: boolean },
  ): AsyncIterable<[id: string, signature: Signature, message: Message<Action | Session>]>
}
0.13.0-next.16

9 months ago

0.13.0-next.15

9 months ago

0.13.0-next.14

9 months ago

0.13.0-next.13

9 months ago

0.12.1

9 months ago

0.13.0-next.12

9 months ago

0.13.0-next.11

9 months ago

0.13.0-next.10

9 months ago

0.13.0-next.9

9 months ago

0.13.0-next.8

9 months ago

0.13.0-next.1

10 months ago

0.13.0-next.3

10 months ago

0.13.0-next.2

10 months ago

0.13.0-next.5

9 months ago

0.13.0-next.4

10 months ago

0.13.0-next.7

9 months ago

0.13.0-next.6

9 months ago

0.11.0

10 months ago

0.12.0

9 months ago

0.10.10

11 months ago

0.10.9

11 months ago

0.10.1

1 year ago

0.10.2

1 year ago

0.10.3

1 year ago

0.10.4

12 months ago

0.10.5

12 months ago

0.10.6

11 months ago

0.10.7

11 months ago

0.10.8

11 months ago

0.10.0

1 year ago

0.10.0-alpha.1

1 year ago

0.8.29

1 year ago

0.10.0-beta.2

1 year ago

0.10.0-beta.3

1 year ago

0.10.0-beta.1

1 year ago

0.10.0-beta.4

1 year ago

0.8.28

1 year ago

0.8.27-patch.21

1 year ago

0.8.27-patch.14

1 year ago

0.8.27-patch.13

1 year ago

0.8.27-patch.16

1 year ago

0.8.27-patch.15

1 year ago

0.8.27-patch.10

1 year ago

0.8.27-patch.6

1 year ago

0.8.27-patch.7

1 year ago

0.8.27-patch.12

1 year ago

0.8.27-patch.8

1 year ago

0.8.27-patch.11

1 year ago

0.8.27-patch.9

1 year ago

0.8.27-patch.20

1 year ago

0.9.1

1 year ago

0.8.27-patch.18

1 year ago

0.8.27-patch.17

1 year ago

0.8.27-patch.19

1 year ago

0.8.27-patch.2

1 year ago

0.8.27-patch.3

1 year ago

0.8.27-patch.4

1 year ago

0.8.27-patch.5

1 year ago

0.8.27-patch.1

1 year ago

0.9.0

1 year ago

0.9.0-next.1

1 year ago

0.8.26-alpha.4

2 years ago

0.8.26-alpha.3

2 years ago

0.8.26-alpha.2

2 years ago

0.8.26

2 years ago

0.8.26-alpha.1

2 years ago

0.8.25

2 years ago

0.8.24

2 years ago

0.8.23

2 years ago

0.8.22

2 years ago

0.8.21

2 years ago

0.8.20

2 years ago

0.8.19

2 years ago

0.8.18

2 years ago

0.8.17

2 years ago

0.8.16

2 years ago

0.8.15

2 years ago

0.8.14-alpha.1

2 years ago

0.8.14

2 years ago

0.8.13

2 years ago

0.8.12

2 years ago

0.8.11

2 years ago

0.8.10

2 years ago

0.8.9

2 years ago

0.8.8

2 years ago

0.8.5

2 years ago

0.8.4

2 years ago

0.8.7

2 years ago

0.8.6

2 years ago

0.8.2-alpha.1

2 years ago

0.8.3

2 years ago

0.8.2

2 years ago

0.8.2-patch.1

2 years ago

0.7.2-alpha.1

2 years ago

0.7.2-alpha.2

2 years ago

0.7.2-alpha.3

2 years ago

0.7.2-alpha.4

2 years ago

0.7.2-alpha.5

2 years ago

0.7.2-alpha.6

2 years ago

0.7.2-alpha.7

2 years ago

0.7.2

2 years ago

0.7.1

2 years ago

0.7.3

2 years ago

0.7.0

2 years ago

0.8.1

2 years ago

0.8.0

2 years ago

0.6.0-alpha2

2 years ago

0.6.0-alpha1

2 years ago

0.6.0-alpha4

2 years ago

0.6.0-alpha3

2 years ago

0.6.0-alpha6

2 years ago

0.6.0-alpha5

2 years ago

0.6.0-alpha7

2 years ago

0.5.0

2 years ago

0.5.1

2 years ago

0.6.1

2 years ago

0.6.0

2 years ago

0.4.9

2 years ago

0.5.0-alpha

2 years ago

0.5.0-alpha4

2 years ago

0.5.0-alpha3

2 years ago

0.5.0-alpha2

2 years ago

0.4.10

2 years ago

0.4.11

2 years ago

0.4.8

2 years ago

0.4.5

2 years ago

0.4.4

2 years ago

0.4.7

2 years ago

0.4.6

2 years ago

0.4.1

2 years ago

0.4.0

2 years ago

0.4.3

2 years ago

0.4.2

2 years ago

0.3.0

2 years ago

0.3.2

2 years ago

0.3.1

2 years ago

0.3.3

2 years ago

0.2.1

2 years ago

0.2.0

2 years ago

0.2.2

2 years ago

0.1.2

2 years ago

0.1.3

2 years ago

0.1.0

2 years ago

0.1.1

2 years ago

0.0.53

2 years ago

0.0.52

2 years ago

0.0.40

3 years ago

0.0.41

3 years ago

0.0.42

3 years ago

0.0.43

3 years ago

0.0.44

3 years ago

0.0.45

3 years ago

0.0.46

3 years ago

0.0.47

3 years ago

0.0.37

3 years ago

0.0.38

3 years ago

0.0.39

3 years ago

0.0.48-pre

3 years ago

0.0.50-pre4

2 years ago

0.0.50-pre3

2 years ago

0.0.50-pre2

2 years ago

0.0.50-pre

2 years ago

0.0.51

2 years ago

0.0.50

2 years ago

0.0.48

3 years ago

0.0.49

2 years ago

0.0.20

3 years ago

0.0.22

3 years ago

0.0.23

3 years ago

0.0.24

3 years ago

0.0.25

3 years ago

0.0.19

3 years ago

0.0.30

3 years ago

0.0.31

3 years ago

0.0.34-alpha6

3 years ago

0.0.32

3 years ago

0.0.33

3 years ago

0.0.34

3 years ago

0.0.35

3 years ago

0.0.36

3 years ago

0.0.34-alpha5

3 years ago

0.0.34-alpha4

3 years ago

0.0.34-alpha3

3 years ago

0.0.34-alpha2

3 years ago

0.0.26

3 years ago

0.0.27

3 years ago

0.0.28

3 years ago

0.0.29

3 years ago

0.0.34-alpha

3 years ago

0.0.17-alpha2

3 years ago

0.0.17-alpha

3 years ago

0.0.17

3 years ago

0.0.10

3 years ago

0.0.11

3 years ago

0.0.16

3 years ago

0.0.2

3 years ago

0.0.3-alpha

3 years ago

0.0.9

3 years ago

0.0.8

3 years ago

0.0.4

3 years ago

0.0.1

3 years ago