mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-16 18:42:30 +03:00
sample-apps: add svelte 3 graphql app (#2256)
This commit is contained in:
parent
8a9901d417
commit
cfd61a86a7
3
community/sample-apps/svelte-apollo/.gitignore
vendored
Normal file
3
community/sample-apps/svelte-apollo/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
.DS_Store
|
||||
node_modules
|
||||
public/bundle.*
|
100
community/sample-apps/svelte-apollo/README.md
Normal file
100
community/sample-apps/svelte-apollo/README.md
Normal file
@ -0,0 +1,100 @@
|
||||
# svelte-graphql-app
|
||||
|
||||
A sample [Svelte 3](https://svelte.dev) app to demonstrate usage of GraphQL Queries, Mutations and Subscriptions with [svelte-apollo](https://github.com/timhall/svelte-apollo), Hasura GraphQL engine and Postgres as database. Forked from the standard svelte [template](https://github.com/sveltejs/template)
|
||||
|
||||
## Deploy Hasura
|
||||
|
||||
- Deploy Postgres and GraphQL Engine on Heroku:
|
||||
|
||||
[![Deploy to
|
||||
heroku](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy?template=https://github.com/hasura/graphql-engine-heroku)
|
||||
|
||||
Please checkout our [docs](https://docs.hasura.io/1.0/graphql/manual/deployment/index.html) for other deployment methods
|
||||
|
||||
- Get the Heroku app URL (say `my-app.herokuapp.com`)
|
||||
- Create `author` table:
|
||||
|
||||
Open Hasura console: visit https://my-app.herokuapp.com on a browser
|
||||
Navigate to `Data` section in the top nav bar and create a table as follows:
|
||||
|
||||
![Create author table](../gatsby-postgres-graphql/assets/add_table.jpg)
|
||||
|
||||
- Insert sample data into `author` table:
|
||||
|
||||
![Insert data into author table](../gatsby-postgres-graphql/assets/insert_data.jpg)
|
||||
|
||||
Verify if the row is inserted successfully
|
||||
|
||||
![Insert data into author table](../gatsby-postgres-graphql/assets/browse_rows.jpg)
|
||||
|
||||
- Similarly, create an article table with the following data model:
|
||||
table: `article`
|
||||
columns: `id`, `title`, `content`, `author_id` (foreign key to `author` table's `id`) and `created_at`
|
||||
|
||||
![Create foreign key for author_id column to author's id](./assets/author_fk.png)
|
||||
|
||||
- Now create a relationship from article table to author table by going to the Relationships tab.
|
||||
|
||||
- Clone this repo:
|
||||
```bash
|
||||
git clone https://github.com/hasura/graphql-engine
|
||||
cd graphql-engine/community/sample-apps/svelte-apollo
|
||||
```
|
||||
|
||||
## Setup App
|
||||
|
||||
Install the dependencies...
|
||||
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
- Open `src/apollo.js` and configure Hasura's GraphQL Endpoint as follows:
|
||||
|
||||
```javascript
|
||||
|
||||
const wsLink = new WebSocketLink({
|
||||
uri: "ws://localhost:8080/v1/graphql",
|
||||
options: {
|
||||
reconnect: true,
|
||||
lazy: true
|
||||
},
|
||||
connectionParams: () => {
|
||||
return { headers: getHeaders() };
|
||||
},
|
||||
});
|
||||
|
||||
const httpLink = new HttpLink({
|
||||
uri: "http://localhost:8080/v1/graphql",
|
||||
headers: getHeaders()
|
||||
});
|
||||
|
||||
```
|
||||
Replace the `uri` argument with your Hasura GraphQL Endpoint for both `wsLink` and `httpLink`
|
||||
|
||||
Start [Rollup](https://rollupjs.org):
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
Navigate to [localhost:5000](http://localhost:5000). You should see your app running. Edit a component file in `src`, save it, and reload the page to see your changes.
|
||||
|
||||
## Deploying to the web
|
||||
|
||||
### With [now](https://zeit.co/now)
|
||||
|
||||
Install `now` if you haven't already:
|
||||
|
||||
```bash
|
||||
npm install -g now
|
||||
```
|
||||
|
||||
Then, from within your project folder:
|
||||
|
||||
```bash
|
||||
now
|
||||
```
|
||||
|
||||
This will deploy the app on Now 2.0 Platform and you have the Svetle app running live :)
|
||||
|
6
community/sample-apps/svelte-apollo/now.json
Normal file
6
community/sample-apps/svelte-apollo/now.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"version": 2,
|
||||
"builds": [
|
||||
{ "src": "package.json", "use": "@now/static-build", "config": { "distDir": "public" } }
|
||||
]
|
||||
}
|
3172
community/sample-apps/svelte-apollo/package-lock.json
generated
Normal file
3172
community/sample-apps/svelte-apollo/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
35
community/sample-apps/svelte-apollo/package.json
Normal file
35
community/sample-apps/svelte-apollo/package.json
Normal file
@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "svelte-graphql-hasura",
|
||||
"version": "1.0.0",
|
||||
"author": "Praveen <praveen@hasura.io>",
|
||||
"devDependencies": {
|
||||
"npm-run-all": "^4.1.5",
|
||||
"rollup": "^1.10.1",
|
||||
"rollup-plugin-commonjs": "^9.3.4",
|
||||
"rollup-plugin-livereload": "^1.0.0",
|
||||
"rollup-plugin-node-resolve": "^4.2.3",
|
||||
"rollup-plugin-replace": "^2.2.0",
|
||||
"rollup-plugin-svelte": "^5.0.3",
|
||||
"rollup-plugin-terser": "^4.0.4",
|
||||
"sirv-cli": "^0.4.0",
|
||||
"svelte": "^3.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "rollup -c",
|
||||
"now-build": "rollup -c",
|
||||
"autobuild": "rollup -c -w",
|
||||
"dev": "run-p start:dev autobuild",
|
||||
"start": "sirv public",
|
||||
"start:dev": "sirv public --dev"
|
||||
},
|
||||
"dependencies": {
|
||||
"apollo-cache-inmemory": "^1.6.0",
|
||||
"apollo-client": "^2.6.0",
|
||||
"apollo-link-http": "^1.5.14",
|
||||
"apollo-link-ws": "^1.0.17",
|
||||
"graphql": "^14.3.0",
|
||||
"graphql-tag": "^2.10.1",
|
||||
"subscriptions-transport-ws": "^0.9.16",
|
||||
"svelte-apollo": "^0.3.0"
|
||||
}
|
||||
}
|
BIN
community/sample-apps/svelte-apollo/public/favicon.png
Normal file
BIN
community/sample-apps/svelte-apollo/public/favicon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.1 KiB |
61
community/sample-apps/svelte-apollo/public/global.css
Normal file
61
community/sample-apps/svelte-apollo/public/global.css
Normal file
@ -0,0 +1,61 @@
|
||||
html, body {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
color: #333;
|
||||
margin: 0;
|
||||
padding: 8px;
|
||||
box-sizing: border-box;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
|
||||
}
|
||||
|
||||
a {
|
||||
color: rgb(0,100,200);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: rgb(0,80,160);
|
||||
}
|
||||
|
||||
label {
|
||||
display: block;
|
||||
}
|
||||
|
||||
input, button, select, textarea {
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
padding: 0.4em;
|
||||
margin: 0 0 0.5em 0;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
input:disabled {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
input[type="range"] {
|
||||
height: 0;
|
||||
}
|
||||
|
||||
button {
|
||||
background-color: #f4f4f4;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
button:active {
|
||||
background-color: #ddd;
|
||||
}
|
||||
|
||||
button:focus {
|
||||
border-color: #666;
|
||||
}
|
17
community/sample-apps/svelte-apollo/public/index.html
Normal file
17
community/sample-apps/svelte-apollo/public/index.html
Normal file
@ -0,0 +1,17 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset='utf8'>
|
||||
<meta name='viewport' content='width=device-width'>
|
||||
|
||||
<title>Svelte app</title>
|
||||
|
||||
<link rel='icon' type='image/png' href='favicon.png'>
|
||||
<link rel='stylesheet' href='global.css'>
|
||||
<link rel='stylesheet' href='bundle.css'>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<script src='bundle.js'></script>
|
||||
</body>
|
||||
</html>
|
48
community/sample-apps/svelte-apollo/rollup.config.js
Normal file
48
community/sample-apps/svelte-apollo/rollup.config.js
Normal file
@ -0,0 +1,48 @@
|
||||
import svelte from 'rollup-plugin-svelte';
|
||||
import resolve from 'rollup-plugin-node-resolve';
|
||||
import commonjs from 'rollup-plugin-commonjs';
|
||||
import replace from 'rollup-plugin-replace';
|
||||
import livereload from 'rollup-plugin-livereload';
|
||||
import { terser } from 'rollup-plugin-terser';
|
||||
|
||||
const production = !process.env.ROLLUP_WATCH;
|
||||
|
||||
export default {
|
||||
input: 'src/main.js',
|
||||
output: {
|
||||
sourcemap: true,
|
||||
format: 'iife',
|
||||
name: 'app',
|
||||
file: 'public/bundle.js'
|
||||
},
|
||||
plugins: [
|
||||
svelte({
|
||||
// enable run-time checks when not in production
|
||||
dev: !production,
|
||||
// we'll extract any component CSS out into
|
||||
// a separate file — better for performance
|
||||
css: css => {
|
||||
css.write('public/bundle.css');
|
||||
}
|
||||
}),
|
||||
|
||||
// If you have external dependencies installed from
|
||||
// npm, you'll most likely need these plugins. In
|
||||
// some cases you'll need additional configuration —
|
||||
// consult the documentation for details:
|
||||
// https://github.com/rollup/rollup-plugin-commonjs
|
||||
resolve({browser: true}),
|
||||
commonjs(),
|
||||
replace({
|
||||
'process.env.NODE_ENV': JSON.stringify('development'),
|
||||
}),
|
||||
|
||||
// Watch the `public` directory and refresh the
|
||||
// browser on changes when not in production
|
||||
!production && livereload('public'),
|
||||
|
||||
// If we're building for production (npm run build
|
||||
// instead of npm run dev), minify
|
||||
production && terser()
|
||||
]
|
||||
};
|
46
community/sample-apps/svelte-apollo/src/AddAuthor.svelte
Normal file
46
community/sample-apps/svelte-apollo/src/AddAuthor.svelte
Normal file
@ -0,0 +1,46 @@
|
||||
<script>
|
||||
import { restore, mutate } from 'svelte-apollo';
|
||||
import { client } from './apollo';
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
const AUTHOR_LIST = gql`
|
||||
query {
|
||||
author(order_by: [{name: asc}]) {
|
||||
name
|
||||
}
|
||||
}
|
||||
`;
|
||||
const ADD_AUTHOR = gql`
|
||||
mutation($name: String!) {
|
||||
insert_author(objects: [{name: $name}]) {
|
||||
affected_rows
|
||||
}
|
||||
}
|
||||
`;
|
||||
let name = '';
|
||||
export let authorCache;
|
||||
|
||||
async function addAuthor(e) {
|
||||
e.preventDefault();
|
||||
try {
|
||||
await mutate(client, {
|
||||
mutation: ADD_AUTHOR,
|
||||
variables: { name }
|
||||
});
|
||||
alert("Added successfully");
|
||||
const finalData = authorCache.data.author;
|
||||
finalData.push({name, '__typename': 'author'});
|
||||
restore(client, AUTHOR_LIST, {author: finalData});
|
||||
// clear input
|
||||
name = '';
|
||||
} catch(error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<form on:submit={addAuthor}>
|
||||
<label for="author">Author</label>
|
||||
<input type="text" id="author-name" bind:value={name} />
|
||||
<button type="submit">Add Author</button>
|
||||
</form>
|
48
community/sample-apps/svelte-apollo/src/App.svelte
Normal file
48
community/sample-apps/svelte-apollo/src/App.svelte
Normal file
@ -0,0 +1,48 @@
|
||||
<script>
|
||||
import ApolloClient from 'apollo-client';
|
||||
import { client } from './apollo';
|
||||
import { setClient } from 'svelte-apollo';
|
||||
import Articles, { preload as articlePreload } from './Articles.svelte';
|
||||
import Authors, { preload as authorPreload } from './Authors.svelte';
|
||||
import AddAuthor from './AddAuthor.svelte';
|
||||
import AuthorsSubscription from './AuthorsSubscription.svelte';
|
||||
|
||||
// Approximate sapper preload
|
||||
const articlePreloading = articlePreload();
|
||||
const authorPreloading = authorPreload();
|
||||
|
||||
setClient(client);
|
||||
</script>
|
||||
|
||||
<style>
|
||||
h1 {
|
||||
color: purple;
|
||||
}
|
||||
</style>
|
||||
|
||||
<section>
|
||||
<h2>Articles (simple query)</h2>
|
||||
|
||||
{#await articlePreloading}
|
||||
<p>Preloading articles....</p>
|
||||
{:then preloaded}
|
||||
<Articles {...preloaded} />
|
||||
{:catch error}
|
||||
<p>Error preloading articles: {error}</p>
|
||||
{/await}
|
||||
|
||||
<h2>Authors (simple query with cache updates)</h2>
|
||||
|
||||
{#await authorPreloading}
|
||||
<p>Preloading authors....</p>
|
||||
{:then preloaded}
|
||||
<Authors {...preloaded} />
|
||||
<h2>Add Author (mutation)</h2>
|
||||
<AddAuthor {...preloaded} />
|
||||
{:catch error}
|
||||
<p>Error preloading authors: {error}</p>
|
||||
{/await}
|
||||
|
||||
<h2>Authors (subscription)</h2>
|
||||
<AuthorsSubscription />
|
||||
</section>
|
44
community/sample-apps/svelte-apollo/src/Articles.svelte
Normal file
44
community/sample-apps/svelte-apollo/src/Articles.svelte
Normal file
@ -0,0 +1,44 @@
|
||||
<script context="module">
|
||||
import gql from 'graphql-tag';
|
||||
import { client } from './apollo';
|
||||
|
||||
const ARTICLES = gql`
|
||||
{
|
||||
article {
|
||||
id
|
||||
title
|
||||
author {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
export async function preload() {
|
||||
return {
|
||||
cache: await client.query({ query: ARTICLES })
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
import { restore, query } from 'svelte-apollo';
|
||||
|
||||
export let cache;
|
||||
restore(client, ARTICLES, cache.data);
|
||||
|
||||
const articles = query(client, { query: ARTICLES });
|
||||
</script>
|
||||
|
||||
<ul>
|
||||
{#await $articles}
|
||||
<li>Loading...</li>
|
||||
{:then result}
|
||||
{#each result.data.article as article (article.id)}
|
||||
<li>{article.title}</li>
|
||||
{:else}
|
||||
<li>No articles found</li>
|
||||
{/each}
|
||||
{:catch error}
|
||||
<li>Error loading articles: {error}</li>
|
||||
{/await}
|
||||
</ul>
|
43
community/sample-apps/svelte-apollo/src/Authors.svelte
Normal file
43
community/sample-apps/svelte-apollo/src/Authors.svelte
Normal file
@ -0,0 +1,43 @@
|
||||
<script context="module">
|
||||
import gql from 'graphql-tag';
|
||||
import { client } from './apollo';
|
||||
|
||||
const AUTHOR_LIST = gql`
|
||||
query {
|
||||
author(order_by: [{name: asc}]) {
|
||||
name
|
||||
}
|
||||
}
|
||||
`;
|
||||
export async function preload() {
|
||||
return {
|
||||
authorCache: await client.query({ query: AUTHOR_LIST })
|
||||
};
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<script>
|
||||
import { restore, query } from 'svelte-apollo';
|
||||
|
||||
export let authorCache;
|
||||
restore(client, AUTHOR_LIST, authorCache.data);
|
||||
|
||||
const authors = query(client, { query: AUTHOR_LIST});
|
||||
|
||||
</script>
|
||||
|
||||
<ul>
|
||||
{#await $authors}
|
||||
<li>Loading...</li>
|
||||
{:then result}
|
||||
{#each result.data.author as author (author.id)}
|
||||
<li>{author.name}</li>
|
||||
{:else}
|
||||
<li>No authors found</li>
|
||||
{/each}
|
||||
{:catch error}
|
||||
<li>Error loading authors: {error}</li>
|
||||
{/await}
|
||||
</ul>
|
||||
|
@ -0,0 +1,30 @@
|
||||
<script context="module">
|
||||
import gql from 'graphql-tag';
|
||||
import { client } from './apollo';
|
||||
|
||||
import { subscribe } from 'svelte-apollo';
|
||||
|
||||
const AUTHOR_LIST = gql`
|
||||
subscription {
|
||||
author(order_by: [{name: asc}]) {
|
||||
name
|
||||
}
|
||||
}
|
||||
`;
|
||||
const authorsList = subscribe(client, { query: AUTHOR_LIST });
|
||||
</script>
|
||||
|
||||
<ul>
|
||||
{#await $authorsList}
|
||||
<li>Loading...</li>
|
||||
{:then result}
|
||||
{#each result.data.author as author (author.id)}
|
||||
<li>{author.name}</li>
|
||||
{:else}
|
||||
<li>No authors found</li>
|
||||
{/each}
|
||||
{:catch error}
|
||||
<li>Error loading authors: {error}</li>
|
||||
{/await}
|
||||
</ul>
|
||||
|
44
community/sample-apps/svelte-apollo/src/apollo.js
Normal file
44
community/sample-apps/svelte-apollo/src/apollo.js
Normal file
@ -0,0 +1,44 @@
|
||||
import ApolloClient from "apollo-client";
|
||||
import { InMemoryCache } from "apollo-cache-inmemory";
|
||||
import { WebSocketLink } from "apollo-link-ws";
|
||||
import { split } from "apollo-link";
|
||||
import { HttpLink } from "apollo-link-http";
|
||||
import { getMainDefinition } from "apollo-utilities";
|
||||
|
||||
const headers = {'content-type': 'application/json'};
|
||||
const getHeaders = () => {
|
||||
return headers;
|
||||
};
|
||||
|
||||
const cache = new InMemoryCache();
|
||||
|
||||
const wsLink = new WebSocketLink({
|
||||
uri: "ws://localhost:8080/v1/graphql",
|
||||
options: {
|
||||
reconnect: true,
|
||||
lazy: true
|
||||
},
|
||||
connectionParams: () => {
|
||||
return { headers: getHeaders() };
|
||||
},
|
||||
});
|
||||
|
||||
const httpLink = new HttpLink({
|
||||
uri: "http://localhost:8080/v1/graphql",
|
||||
headers: getHeaders()
|
||||
});
|
||||
|
||||
const link = split(
|
||||
({ query }) => {
|
||||
const { kind, operation } = getMainDefinition(query);
|
||||
return kind === "OperationDefinition" && operation === "subscription";
|
||||
},
|
||||
wsLink,
|
||||
httpLink
|
||||
);
|
||||
|
||||
export const client = new ApolloClient({
|
||||
link,
|
||||
cache
|
||||
});
|
||||
|
7
community/sample-apps/svelte-apollo/src/main.js
Normal file
7
community/sample-apps/svelte-apollo/src/main.js
Normal file
@ -0,0 +1,7 @@
|
||||
import App from './App.svelte';
|
||||
|
||||
const app = new App({
|
||||
target: document.body,
|
||||
});
|
||||
|
||||
export default app;
|
Loading…
Reference in New Issue
Block a user