Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integrating with Ember #120

Open
dustinfarris opened this issue Sep 12, 2016 · 11 comments
Open

Integrating with Ember #120

dustinfarris opened this issue Sep 12, 2016 · 11 comments

Comments

@dustinfarris
Copy link
Contributor

dustinfarris commented Sep 12, 2016

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
Copy link
Contributor Author

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
Copy link
Contributor Author

dustinfarris commented Oct 20, 2016

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.

@mattkrick
Copy link
Owner

whoa, that's amazing!

@dustinfarris
Copy link
Contributor Author

dustinfarris commented Oct 31, 2016

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

@mattkrick
Copy link
Owner

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
#120 (comment),
or mute the thread
https://github.com/notifications/unsubscribe-auth/AFQjv67NDw-wHZl50R8banlrYwUV1Fjcks5q5knEgaJpZM4J65tY
.

@dustinfarris
Copy link
Contributor Author

dustinfarris commented Nov 20, 2016

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).

@mattkrick
Copy link
Owner

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.

@dustinfarris
Copy link
Contributor Author

dustinfarris commented Nov 26, 2016

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
Copy link
Contributor Author

Slightly better example (with sub-query!)

ember-twiddle.com/f2a8a4123c65c4871a885444978efe65

@dustinfarris
Copy link
Contributor Author

dustinfarris commented Dec 16, 2016

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
Copy link
Contributor Author

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');
    });
  });
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants