cashay icon indicating copy to clipboard operation
cashay copied to clipboard

Integrating with Ember

Open dustinfarris opened this issue 9 years ago • 11 comments

This is a placeholder issue for me (and anyone else interested) to work on integrating Cashay with Ember.

This is my current thinking (TODO list):

  • Write a graphql schema/server using Ember CLI Mirage as a development/testing backend (Mirage would play the part of db and server for dev/testing)
  • Figure out how to get the client-safe schema in a way that does not expose Mirage in a production environment (options include a manual cli that cashay provides, or adding a build step that does this using cashay's exsiting recipes for webpack as a reference)
  • Use ember-redux to bring in cashay's reducer
  • Create cashay singleton and expose as an Ember service that can then be used from any route/component/etc

It may be desirable to create an Ember addon to provide tooling for the above steps.

Currently cashay and graphql have to be imported via browserify.

dustinfarris avatar Sep 12 '16 18:09 dustinfarris

Quick update:

  • I am almost done with an ember addon that will generate a client-safe schema auto-magically (via broccoli) and provide the necessary boilerplate for cashay's redux reducer (via ember-redux).
  • Ember CLI Mirage won't be required, but I'm taking care to make sure that it is compatible (currently waiting on a version bump from Pretender so that we can use the promise returned by graphql in a test/dev environment)

dustinfarris avatar Oct 12 '16 02:10 dustinfarris

broccoli plugin is finished and working: https://github.com/dustinfarris/broccoli-cashay-schema

I am almost done with ember-cashay, an Ember addon that will make using cashay a one-liner at the command prompt. ~~Hope to release tomorrow.~~ It is working, just finishing up documentation and tests.

dustinfarris avatar Oct 20 '16 22:10 dustinfarris

whoa, that's amazing!

mattkrick avatar Oct 20 '16 22:10 mattkrick

ember-cashay is now on GitHub: https://github.com/dustinfarris/ember-cashay

This initial implementation proves that cashay and ember can work together (and remarkably well, I might add).

Working now:

  • automatic generation of client-safe schema (using broccoli plugin)
  • cashay queries
  • integration with ember-cli-mirage for testing

Remaining before v0.1.0 release:

  • ember default generator to smooth out the installation process
  • configuration support
  • better documentation (maybe a Twiddle to demonstrate usage)

To see this in action, check out the dummy app ("dummy" apps are internal apps created for and used by Ember addons to run acceptance tests against) in the repo.

For example, here is a container component making a query: https://github.com/dustinfarris/ember-cashay/blob/master/tests/dummy/app/components/users-list.js

dustinfarris avatar Oct 31 '16 20:10 dustinfarris

Whoa, this is huge! If you got an example app I'd love to check it out! The caahay-sandbox is crazy out of date, I'm hoping to find the time to showcase sockets in it soon

On Oct 31, 2016 1:04 PM, "Dustin Farris" [email protected] wrote:

ember-cashay is now on GitHub: https://github.com/ dustinfarris/ember-cashay

This initial implementation proves that cashay and ember can work together (and remarkably well, I might add).

Working now:

  • automatic generation of client-safe schema
  • cashay queries
  • integration with ember-cli-mirage for testing

Remaining before v0.1.0 release:

  • ember default generator to smooth out the installation process
  • better documentation (maybe a Twiddle to demonstrate usage)

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/mattkrick/cashay/issues/120#issuecomment-257404621, or mute the thread https://github.com/notifications/unsubscribe-auth/AFQjv67NDw-wHZl50R8banlrYwUV1Fjcks5q5knEgaJpZM4J65tY .

mattkrick avatar Oct 31 '16 20:10 mattkrick

Update:

ember-cashay v0.1.0 has been released and works beautifully.

I am working on support for mutations (mostly just adding tests to make sure everything works as designed) and will then release v0.2.0 along with a blog post and a Twiddle (example app running in a sandbox that visitors can tinker with).

Getting the Twiddle working is currently blocked. ember-cashay browserifies Cashay, and Cashay+deps is huge which causes Twiddle to timeout when it is building the project. I am hoping that if #140 or something similar is merged, the size of Cashay will be reduced dramatically (no babel-runtime).

dustinfarris avatar Nov 20 '16 23:11 dustinfarris

just merged your PR, thank you! Another large dep that i'd like to get rid of is GraphQL itself. Currently, aside from a handful of string constants, cashay just uses parse and print. If you have a good packager builder, then you can employ tree shaking to get just what you need. I don't think browserify does that though, so you're stuck with the entire thing.

mattkrick avatar Nov 20 '16 23:11 mattkrick

Update:

It gives me great pleasure to announce that I have a working Twiddle showing off ember-cashay!

ember-twiddle.com/f2a8a4123c65c4871a885444978efe65

The demo is very basic. Two queries demonstrated: one that returns a string, and another that returns results from a database lookup (via ember-cli-mirage).

There is a caveat with the Twiddle. The server graphql schema shown cannot be modified. This is because of the way Twiddle works—the asset-pipeline is only run when the addon is first installed, so the client-safe schema is generated once and once only. The rest of the application code can be tinkered with since it lives in the browser, but the graphql schema file is "for show" only.

Additionally, ember-cashay v0.2.0 has been released. This version mainly contains optimizations needed for Twiddle.

For the super curious, I had to create a wrapper addon to get this to work. More details in the ember-cashay-twiddle-demo README.

Next up: mutations

dustinfarris avatar Nov 26 '16 13:11 dustinfarris

Slightly better example (with sub-query!)

ember-twiddle.com/f2a8a4123c65c4871a885444978efe65

dustinfarris avatar Nov 26 '16 19:11 dustinfarris

Update:

ember-cashay v0.5.0 has been released

I can now say with a straight face that Ember+Cashay is a thing.

Mutations are tested and working well.

Browserify has been stripped (thanks to a broccoli-webpack plugin I found) so you can use cashay in Ember the same way you would anywhere else.

import Ember from 'ember'
import connect from 'ember-redux/components/connect';
import hbs from 'htmlbars-inline-precompile';

import { cashay } from 'cashay';

const usersQuery = `
{
  users {
    id
    name
  }
}`;

const stateToComputed = () => {
  const { 
    status,
    data: { users } 
  } = cashay.query(usersQuery, {
    op: 'UsersComponent',
    mutationHandlers: {
      createUser(optimisticVariables, queryResponse, currentResponse) {
        if (queryResponse) {
          currentResponse.users.push(queryResponse);
          return currentResponse;
        }
      }
    }
  });
  return {
    users,
    isLoading: status === 'loading'
  }
};

const UsersComponent = Ember.Component.extend({
  actions: {
    addUser(variables) {
      cashay.mutate('createUser', { variables });
    }
  },

  layout: hbs`
    <h2>All Users</h2>
    {{#each users as |user|}}
      {{user-details user=user}}
    {{/each}}
    <hr>
    {{add-user-form submit=(action "addUser")}}
  `
});

export default connect(stateToComputed)(UsersComponent);

This works well, but there is more to do to smooth out the edges. react-apollo has a neat helper (called "graphql") that connects a component to a query and mutation and does a bunch of other apollo-specific stuff. I'd like to do something similar but much simpler in ember-cashay that basically takes care of the redux subscription and props assignment for you without having to define stateToComputed.

e.g. something like:

import { cash } from 'ember-cashay';

const usersQuery = `
{
  users {
    id
    name
  }
}`;

const UsersComponent = Component.extend({
  layout: hbs`
    {{#each users as |user|}}
      Hi, {{user.name}}!
    {{/each}}
  `
});

export default cash(userQuery)(UsersComponent);

(obviously i haven't given the name much thought) — stay tuned!

dustinfarris avatar Dec 16 '16 09:12 dustinfarris

Update:

ember-cashay v0.6.0 has been released

This includes tests and support for @live fields.

The general usage works exactly as you would expect.

Testing was a little more complicated when introducing websockets. To make this easier, I brought in mock-socket to simulate a vanilla websocket server.

The async nature of websockets is also tricky. To smooth this out I've provided 2 new test helpers:

  • waitForSubscriptions is a waiter function that polls cashay.cachedQueries and cashay.cachedSubscriptions looking for anything that hasn't resolved yet.

  • moduleForAcceptance takes care of registering the waiter function, which causes it to run after every async test operation. It also tears down cashay, mirage, and the fake websocket server after every test.

If you set everything up as I have, you can have a query like:

const projectQuery = `
{
  project (id: $project_id) @live {
    id
    title
    projectTodos @live {
      id
      description
    }
  }
}
`;

and write tests like this:

moduleForAcceptance('Acceptance | Todos');


test('live updates', function(assert) {
  const project = server.create('project', { name: 'IndustryMaps' });
  server.createList('todo', 3, { project });

  visit(`/project/${project.id}`);

  andThen(() => {
    assert.equal(find('.project-todos .todo').length, 3, 'initial todos should be rendered');

    // A new todo has arrived on the server!  Notify clients!
    window.socketServer.send({
      topic: `projectTodos:${project.id}`,
      data: {
        type: 'add',
        objects: [{
          id: "1234567",
          description: "Freshly Minted Todo!"
        }]
      }
    });

    andThen(() => {
      assert.equal(find('.project-todos .todo').length, 4, 'a new todo should be rendered');
    });
  });
});

dustinfarris avatar Jan 13 '17 07:01 dustinfarris