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

Generate types #110

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions examples/6-typegen/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
node_modules
.build
lib
.cache
29 changes: 29 additions & 0 deletions examples/6-typegen/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
## About

This example is "borrowed" from the awesome urql repository [here](https://github.com/FormidableLabs/urql/tree/master/examples/1-getting-started).

This example demonstrates a simple mst-gql project (without scaffolding set up)

## Usage

#### 0. install `mst-gql` dependencies (within the parent `mst-gql` directory)

```bash
yarn
```

#### 1. Install dependencies (within this example's folder)

```bash
yarn
```

#### 2. Start server

```bash
yarn start
```

#### 3. Open browser

Navigate to example at [http://localhost:3000/](http://localhost:3000/).
48 changes: 48 additions & 0 deletions examples/6-typegen/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{
"name": "@mst-gql/typegen",
"version": "1.0.0",
"private": true,
"license": "MIT",
"scripts": {
"start:server": "node ./src/server/index.js",
"start:client": "sleep 1 && yarn scaffold && parcel serve -p 3000 public/index.html",
"scaffold": "../../generator/mst-gql-scaffold.js --roots 'Todo' --excludes 'CacheControlScope,Query,Subscription' --outDir src/app/models/ --format ts http://localhost:3001/graphql",
"postinstall": "../../node_modules/.bin/relative-deps",
"start": "run-p start:server start:client",
"type-check": "tsc --noEmit",
"type-check:watch": "yarn type-check -- --watch"
},
"dependencies": {
"@types/graphql": "^14.2.3",
"@types/jest": "^24.0.16",
"@types/react": "^16.8.24",
"@types/react-dom": "^16.8.5",
"apollo-server-express": "^2.8.1",
"arg": "^4.1.1",
"cors": "^2.8.5",
"express": "^4.17.1",
"graphql": "^14.3.0",
"graphql-playground-middleware-express": "^1.7.12",
"graphql-tag": "^2.10.1",
"isomorphic-fetch": "^2.2.1",
"jest": "^24.8.0",
"mobx": "^5.13.0",
"mobx-react": "^6.1.1",
"mobx-state-tree": "^3.14.1",
"mst-gql": "^0.1.2",
"react": "^16.8.6",
"react-dom": "^16.8.6"
},
"devDependencies": {
"@babel/core": "^7.5.5",
"npm-run-all": "^4.1.5",
"parcel": "^1.12.3",
"typescript": "^3.4.5"
},
"resolutions": {
"graphql": "14.3.0"
},
"relativeDependencies": {
"mst-gql": "../../"
}
}
14 changes: 14 additions & 0 deletions examples/6-typegen/public/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>MST-GQL Getting Started Example</title>
</head>

<body>
<div id="root"></div>
<script type="text/javascript" src="../src/app/index.tsx"></script>
</body>
</html>
31 changes: 31 additions & 0 deletions examples/6-typegen/src/app/Home.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React from "react"
import { observer } from "mobx-react-lite"
import { useQuery } from "./models/reactUtils"
import { Query } from "mst-gql"

import { TodoType } from "./models"
import { Error, Loading, Todo } from "./components"

export const Home = observer(() => {
const { loading, error, data, query, store } = useQuery(store =>
store.queryTodos()
)

if (error) return <Error>{error.message}</Error>
if (data)
return (
<>
<ul>
{data.todos.map((todo: TodoType) => (
<Todo key={todo.id} todo={todo} />
))}
</ul>
{loading ? (
<Loading />
) : (
<button onClick={query!.refetch}>Refetch</button>
)}
</>
)
return <Loading />
})
9 changes: 9 additions & 0 deletions examples/6-typegen/src/app/components/Error.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import React, { FC } from "react"

export const Error: FC = props => (
<>
<h4>Error</h4>
<p>Something went wrong</p>
<p>Message: {props.children}</p>
</>
)
3 changes: 3 additions & 0 deletions examples/6-typegen/src/app/components/Loading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import React from "react"

export const Loading = () => <p>Loading...</p>
17 changes: 17 additions & 0 deletions examples/6-typegen/src/app/components/Todo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import * as React from "react"
import { observer } from "mobx-react-lite"

import { TodoType } from "../models"
import { useQuery } from "../models/reactUtils"

export const Todo = observer(({ todo }: { todo: TodoType }) => {
const { setQuery, loading, error } = useQuery(undefined)

return (
<li onClick={() => setQuery(todo.toggle())}>
<p className={`${todo.complete ? "strikethrough" : ""}`}>{todo.text}</p>
{error && <span>Failed to update</span>}
{loading && <span>(updating)</span>}
</li>
)
})
3 changes: 3 additions & 0 deletions examples/6-typegen/src/app/components/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from "./Error"
export * from "./Loading"
export * from "./Todo"
46 changes: 46 additions & 0 deletions examples/6-typegen/src/app/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
html {
background: #488;
font-family: sans-serif;
}

#root {
width: 100%;
display: flex;
justify-content: center;
}

main {
width: 400px;
}

h1 {
color: #2d4a4a;
}

h4 {
margin: 0;
margin-bottom: 5px;
}

ul {
list-style-type: none;
padding: 0;
}

li {
background: #fff;
display: flex;
justify-content: space-between;
box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.2);
padding: 20px;
margin: 20px 0;
border-radius: 4px;
}

li span {
color: #999;
}

.strikethrough {
text-decoration: line-through;
}
24 changes: 24 additions & 0 deletions examples/6-typegen/src/app/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import React from "react"
import * as ReactDOM from "react-dom"
import { createHttpClient } from "mst-gql"

import "./index.css"

import { RootStore } from "./models/RootStore"
import { StoreContext } from "./models/reactUtils"
import { Home } from "./Home"

const rootStore = RootStore.create(undefined, {
gqlHttpClient: createHttpClient("http://localhost:3001/graphql")
})

export const App: React.FC = () => (
<StoreContext.Provider value={rootStore}>
<main>
<h1>Todos</h1>
<Home />
</main>
</StoreContext.Provider>
)

ReactDOM.render(<App />, document.getElementById("root"))
49 changes: 49 additions & 0 deletions examples/6-typegen/src/app/models/RootStore.base.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/* This is a mst-gql generated file, don't modify it manually */
/* eslint-disable */
/* tslint:disable */
import { types } from "mobx-state-tree"
import { MSTGQLStore, configureStoreMixin, QueryOptions } from "mst-gql"

import { TodoModel, TodoModelType } from "./TodoModel"
import { todoModelPrimitives, TodoModelSelector } from "./TodoModel.base"
import { UserModel, UserModelType } from "./UserModel"
import { userModelPrimitives, UserModelSelector } from "./UserModel.base"


export type CreateTodoInput = {
id: string
text: string
owner: string
complete: boolean | undefined
}
/**
* Store, managing, among others, all the objects received through graphQL
*/
export const RootStoreBase = MSTGQLStore
.named("RootStore")
.extend(configureStoreMixin([['Todo', () => TodoModel], ['User', () => UserModel]], ['Todo']))
.props({
todos: types.optional(types.map(types.late(() => TodoModel)), {})
})
.actions(self => ({
queryTodos(variables?: { }, resultSelector: string | ((qb: TodoModelSelector) => TodoModelSelector) = todoModelPrimitives.toString(), options: QueryOptions = {}) {
return self.query<{ todos: TodoModelType[]}>(`query todos { todos {
${typeof resultSelector === "function" ? resultSelector(new TodoModelSelector()).toString() : resultSelector}
} }`, variables, options)
},
queryUsers(variables?: { }, resultSelector: string | ((qb: UserModelSelector) => UserModelSelector) = userModelPrimitives.toString(), options: QueryOptions = {}) {
return self.query<{ users: UserModelType[]}>(`query users { users {
${typeof resultSelector === "function" ? resultSelector(new UserModelSelector()).toString() : resultSelector}
} }`, variables, options)
},
mutateToggleTodo(variables: { id: string }, resultSelector: string | ((qb: TodoModelSelector) => TodoModelSelector) = todoModelPrimitives.toString(), optimisticUpdate?: () => void) {
return self.mutate<{ toggleTodo: TodoModelType}>(`mutation toggleTodo($id: ID!) { toggleTodo(id: $id) {
${typeof resultSelector === "function" ? resultSelector(new TodoModelSelector()).toString() : resultSelector}
} }`, variables, optimisticUpdate)
},
mutateCreateTodo(variables: { todo: CreateTodoInput }, resultSelector: string | ((qb: TodoModelSelector) => TodoModelSelector) = todoModelPrimitives.toString(), optimisticUpdate?: () => void) {
return self.mutate<{ createTodo: TodoModelType}>(`mutation createTodo($todo: CreateTodoInput!) { createTodo(todo: $todo) {
${typeof resultSelector === "function" ? resultSelector(new TodoModelSelector()).toString() : resultSelector}
} }`, variables, optimisticUpdate)
},
}))
11 changes: 11 additions & 0 deletions examples/6-typegen/src/app/models/RootStore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Instance } from "mobx-state-tree"
import { RootStoreBase } from "./RootStore.base"

export interface RootStoreType extends Instance<typeof RootStore.Type> {}

export const RootStore = RootStoreBase.actions(self => ({
// This is an auto-generated example action.
log() {
console.log(JSON.stringify(self))
}
}))
41 changes: 41 additions & 0 deletions examples/6-typegen/src/app/models/TodoModel.base.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/* This is a mst-gql generated file, don't modify it manually */
/* eslint-disable */
/* tslint:disable */

import { types } from "mobx-state-tree"
import { MSTGQLObject, QueryBuilder } from "mst-gql"
import { UserModel } from "./UserModel"
import { UserModelSelector } from "./UserModel.base"
import { RootStoreType } from "./index"


/**
* TodoBase
* auto generated base class for the model TodoModel.
*/
export const TodoModelBase = MSTGQLObject
.named('Todo')
.props({
__typename: types.optional(types.literal("Todo"), "Todo"),
id: types.identifier,
text: types.maybeNull(types.string),
complete: types.maybeNull(types.boolean),
owner: types.maybeNull(types.late(() => UserModel)),
})
.views(self => ({
get store() {
return self.__getStore<RootStoreType>()
}
}))

export class TodoModelSelector extends QueryBuilder {
get id() { return this.__attr(`id`) }
get text() { return this.__attr(`text`) }
get complete() { return this.__attr(`complete`) }
owner(builder?: string | UserModelSelector | ((selector: UserModelSelector) => UserModelSelector)) { return this.__child(`owner`, UserModelSelector, builder) }
}
export function selectFromTodo() {
return new TodoModelSelector()
}

export const todoModelPrimitives = selectFromTodo().text.complete
39 changes: 39 additions & 0 deletions examples/6-typegen/src/app/models/TodoModel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { Instance } from "mobx-state-tree"
import { TodoModelBase } from "./TodoModel.base"
import { Query } from "mst-gql"

import { UserType } from "./UserModel"
import { RootStoreType } from "./RootStore"

/* The TypeScript type of an instance of TodoModel */
export interface TodoModelType extends Instance<typeof TodoModel.Type> {}

/* A graphql query fragment builders for TodoModel */
export {
selectFromTodo,
todoModelPrimitives,
TodoModelSelector
} from "./TodoModel.base"

export interface TodoType {
__typename: "Todo"
id: string
text: string | null
complete: boolean | null
owner: UserType | null
toggle: () => Query<{ toggleTodo: TodoType }>
store: RootStoreType
}

/**
* TodoModel
*/
export const TodoModel = TodoModelBase.actions(self => ({
toggle(): Query<{
toggleTodo: TodoType
}> {
return self.store.mutateToggleTodo({ id: self.id }, undefined, () => {
self.complete = !self.complete
})
}
}))
Loading