<!DOCTYPE html>
<html>

  <head>
    <base href="." />
    <title>Apollo Angular 2 example</title>
    <link rel="stylesheet" href="style.css" />
    <script src="https://unpkg.com/core-js/client/shim.min.js"></script>
    <script src="https://unpkg.com/zone.js@0.6.23?main=browser"></script>
    <script src="https://unpkg.com/reflect-metadata@0.1.3"></script>
    <script src="https://unpkg.com/systemjs@0.19.31/dist/system.js"></script>
    <script src="https://wzrd.in/standalone/frontpage-app-dependencies@1.0.1"></script>
    <script src="systemjs.config.js"></script>
    <script>
    System.import('app')
      .catch(console.error.bind(console));
  </script>
  </head>

  <body>
    <app-root>
    loading...
  </app-root>
  </body>

</html>
body {
  margin: 0;
  padding: 0;
  font-family: sans-serif;
}
var paths = {
  'npm:': 'https://unpkg.com/'
};

var map = {
  'app':                                'src',

  '@angular/core':                      'npm:@angular/core/bundles/core.umd.js',
  '@angular/common':                    'npm:@angular/common/bundles/common.umd.js',
  '@angular/compiler':                  'npm:@angular/compiler/bundles/compiler.umd.js',
  '@angular/platform-browser':          'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
  '@angular/platform-browser-dynamic':  'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
  'rxjs':                               'npm:rxjs@5.0.0-beta.12',
  'ts':                                 'npm:plugin-typescript@4.0.10/lib/plugin.js',
  'typescript':                         'npm:typescript@2.0.0/lib/typescript.js',
  
  'apollo-client':                      'npm:apollo-client',
  'apollo-client-rxjs':                 'npm:apollo-client-rxjs',
  'angular2-apollo':                    'npm:angular2-apollo',
  
  'lodash':                             'npm:lodash',
  'graphql':                            'npm:graphql',
  'whatwg-fetch':                       'npm:whatwg-fetch',
  'graphql-tag':                        'npm:graphql-tag',
  'symbol-observable':                  'npm:symbol-observable', // XXX waiting for apollo-client@0.4.15
  'redux':                              'npm:redux/dist/redux.min.js'
};

//packages tells the System loader how to load when no filename and/or no extension
var packages = {
  'app':                        { main: './main.ts',  defaultExtension: 'ts' },
  'rxjs':                       { defaultExtension: 'js', main: 'index.js' },
  'symbol-observable':          { defaultExtension: 'js', main: 'index.js' },
  'lodash':                     { defaultExtension: 'js', main: 'index.js' },
  
  'apollo-client':              { main: './index.js', defaultExtension: 'js' },
  'apollo-client-rxjs':         { main: './build/src/index.js', defaultExtension: 'js' },
  'angular2-apollo':            { main: './build/src/index.js', defaultExtension: 'js' },
  
  'whatwg-fetch':               { main: './fetch.js', defaultExtension: 'js' },
  'redux':                      { format: 'cjs', defaultExtension: 'js' }
};


[
  'assign',
  'countby',
  'clonedeep',
  'flatten',
  'forin',
  'forown',
  'has',
  'identity',
  'includes',
  'isarray',
  'isequal',
  'isnull',
  'isnumber',
  'isobject',
  'isstring',
  'isfunction',
  'isundefined',
  'isplainobject',
  'keys',
  'keysin',
  'mapvalues',
  'omit',
  'pick',
  'rest',
  '_baseclone',
  '_baseeach',
  '_baseflatten',
  '_basefor',
  '_baseiteratee',
  '_basetostring',
  '_stringtopath',
  '_root'
].forEach((name) => {
  var pkg = `lodash.${name}`;

  map[pkg] = `npm:${pkg}`;
  packages[pkg] = {
    defaultExtension: 'js',
    main: 'index.js'
  };
});

  
System.config({
  transpiler: 'ts',
  typescriptOptions: {
    tsconfig: true
  },
  meta: {
    'typescript': {
      'exports': 'ts'
    }
  },
  paths: paths,
  //map tells the System loader where to look for things
  map: map,
  //packages defines our app package
  packages: packages
});
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { AppModule } from './app/app.module';

platformBrowserDynamic().bootstrapModule(AppModule);
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  styles: [`
    app-root {
      text-align: center;
    }
    
    .App-logo {
      animation: App-logo-spin infinite 20s linear;
      height: 80px;
    }
    
    .App-header {
      background-color: #222;
      height: 150px;
      padding: 20px;
      color: white;
    }
    
    .App-intro {
      font-size: large;
    }
    
    @keyframes App-logo-spin {
      from { transform: rotate(0deg); }
      to { transform: rotate(360deg); }
    }
  `],
  template: `
    <app-post-list></app-post-list>
  `
})
export class AppComponent {}
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { ApolloModule } from 'angular2-apollo';

import { AppComponent } from './app.component';
import { PostListComponent } from './post/post-list.component';
import { PostUpvoterComponent } from './post/post-upvoter.component';
import { client } from './client';

@NgModule({
  declarations: [
    AppComponent,
    PostListComponent,
    PostUpvoterComponent
  ],
  imports: [
    BrowserModule,
    ApolloModule.withClient(client)
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule {}
import { Component, OnInit } from '@angular/core';
import { Angular2Apollo, ApolloQueryObservable } from 'angular2-apollo';

const gql = frontpageAppDependencies['graphql-tag'].default

@Component({
  selector: 'app-post-list',
  template: `
    <ul>
      <li *ngFor="let post of posts | async | select: 'posts'">
        {{post.title}} by {{post.author.firstName}} {{post.author.lastName}}
        ({{post.votes}} votes)
        <app-post-upvoter [postId]="post.id"></app-post-upvoter>
      </li>
    </ul>
  `
})
export class PostListComponent implements OnInit {
  posts: ApolloQueryObservable<any>;
  
  constructor(private apollo: Angular2Apollo) {}

  ngOnInit() {
    this.posts = this.apollo.watchQuery({
      query: gql`
        query allPosts {
          posts {
            id
            title
            votes
            author {
              id
              firstName
              lastName
            }
          }
        }
      `,
    });
  }
}
import { Component, Input } from '@angular/core';
import { Angular2Apollo } from 'angular2-apollo';

const gql = frontpageAppDependencies['graphql-tag'].default;

@Component({
  selector: 'app-post-upvoter',
  template: `
    <button (click)="upvote()">
      Upvote
    </button>
  `
})
export class PostUpvoterComponent {
  @Input() postId: number;

  constructor(private apollo: Angular2Apollo) {}

  upvote() {
    this.apollo.mutate({
      mutation: gql`
        mutation upvotePost($postId: Int!) {
          upvotePost(postId: $postId) {
            id
            votes
          }
        }
      `,
      variables: {
        postId: this.postId,
      },
    });
  }
}
import ApolloClient, { createNetworkInterface } from 'apollo-client';
import { find, filter } from 'lodash';

// src/schema/schema.js

const { makeExecutableSchema } = frontpageAppDependencies['graphql-tools'];

const typeDefinitions = `
type Author {
  id: Int! # the ! means that every author object _must_ have an id
  firstName: String
  lastName: String
  posts: [Post] # the list of Posts by this author
}

type Post {
  id: Int!
  title: String
  author: Author
  votes: Int
}

# the schema allows the following query:
type Query {
  posts: [Post]
}

# this schema allows the following mutation:
type Mutation {
  upvotePost (
    postId: Int!
  ): Post
}

# we need to tell the server which types represent the root query
# and root mutation types. We call them RootQuery and RootMutation by convention.
schema {
  query: Query
  mutation: Mutation
}
`;

// src/schema/resolvers.js

const authors = [
  { id: 1, firstName: 'Tom', lastName: 'Coleman' },
  { id: 2, firstName: 'Sashko', lastName: 'Stubailo' },
];

const posts = [
  { id: 1, authorId: 1, title: 'Introduction to GraphQL', votes: 2 },
  { id: 2, authorId: 2, title: 'GraphQL Rocks', votes: 3 },
  { id: 3, authorId: 2, title: 'Advanced GraphQL', votes: 1 },
];

const resolveFunctions = {
  Query: {
    posts() {
      return posts;
    },
  },
  Mutation: {
    upvotePost(_, { postId }) {
      const post = find(posts, { id: postId });
      if (!post) {
        throw new Error(`Couldn't find post with id ${postId}`);
      }
      post.votes += 1;
      return post;
    }
  },
  Author: {
    posts(author) {
      return filter(posts, { authorId: author.id });
    },
  },
  Post: {
    author(post) {
      return find(authors, { id: post.authorId });
    },
  }
}


// src/schema/index.js

const schema = makeExecutableSchema({
  typeDefs: typeDefinitions,
  resolvers: resolveFunctions,
});

// in-browser-network-interface.js
const { execute } = frontpageAppDependencies.graphql;

class InBrowserNetworkInterface {
  constructor({ schema }) {
    this.schema = schema;
  }

  query(request) {
    return execute(
      this.schema,
      request.query,
      {},
      {},
      request.variables,
      request.operationName);
  }
}

const networkInterface = new InBrowserNetworkInterface({ schema });
export const client = new ApolloClient({
  networkInterface,
  dataIdFromObject: r => r.id,
});
{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",
    "moduleResolution": "node",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": false,
    "noImplicitAny": true,
    "suppressImplicitAnyIndexErrors": true
  }
}