DEV Community

Daniel Neveux
Daniel Neveux

Posted on

1 1

Wizar devlog 08 - Ravioli transformation

Achievement of the week so far:

User Stories:

  • user can connect Crafter observable to React. I finished the first version of Crafter React which makes React (really) reactive to Cragter observables changes. It was mainly a copy past of Mobx-React but without the hooks for now.
  • user can add Transformation to a Ravioli Component In the SAM pattern the model is isolated from the view. That makes possibles to write application in "privacy first" because what the world sees about your component is not necessarily the exact copy of the underlying model. Eg. As a player I can't see the contains of other players inventory.
  • transformation applies only on certains control state. To keep a good developer experience, Ravioli provides an API to effectively split your code. Instead of having one representation which handles multiple cases, we can easily put many representation as needed, depending on the control states (and many others params if needed). Eg. As a player, I can see the other dead players inventory. Instead of using if/else, let's be more declarative and use two different transformation. One for an alive player, one for a dead player. See the example below.

Technical Stories:

  • refactor Crafter to make it compatible on Node.js app. Basically removed a singleton and implements a container pattern to isolate each observers/observables context.
test('representation predicate', function() {
  const player = component(object({
    name: string(),
    health: number(),
    inventory: array(object({ id: string(), quantity: number() }))
  }))
    // Define which control state my player can be
    .setControlStatePredicate('isAlive', ({model}) => model.health > 0)
    .setControlStatePredicate('isDead', ({model}) => model.health <= 0)

    // Define acceptors
    .addAcceptor('setHealth', model => ({mutator({hp}: {hp: number}): void { model.health += hp }}))

    // Define actions (if you use TS, it will autocomplete magically only with possible mutations <3 )
    .addActions({ hit: () => [{ type: 'setHealth', payload: {hp: -10}}]})

    // How the world will see me?
    .setTransformation('alive', {
      predicate: 'isAlive', // I am alive, no inventory visible.
      computation: ({modelSnapshot}) => ({ name: modelSnapshot.name, health: modelSnapshot.health})
    })
    .setTransformation('dead', {
      predicate: 'isDead', // I died. Be my guest. Loot me.
      computation: ({modelSnapshot}) => ({ name: modelSnapshot.name, inventory: modelSnapshot.inventory })
    })

    // Instantiate a player
    .create({
      name: 'Fraktar',
      health: 10,
      inventory: [
        { id: 'sword', quantity: 1},
        { id: 'shield', quantity: 1},
      ]
    })

  // Player is alive, I can't see its inventory.
  expect(player.state.representation.inventory).toBeUndefined()

  // Take that!
  player.actions.hit()

  // Haha, here is one a lovely sword!
  expect(player.state.representation.inventory).toBeDefined()
})

Heroku

This site is built on Heroku

Join the ranks of developers at Salesforce, Airbase, DEV, and more who deploy their mission critical applications on Heroku. Sign up today and launch your first app!

Get Started

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay