Skip to content

Commit 029a6f2

Browse files
committed
Basic version of GraphQL server returning latest home sensors reading
1 parent 37c9909 commit 029a6f2

File tree

10 files changed

+2132
-48
lines changed

10 files changed

+2132
-48
lines changed

.eslintrc.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"extends": "airbnb-base",
3+
"rules": {
4+
"max-len": 1,
5+
}
6+
}

package-lock.json

Lines changed: 1991 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,15 @@
1010
"dependencies": {
1111
"@google-cloud/bigquery": "^4.7.0",
1212
"apicache": "^1.5.3",
13-
"express": "^4.17.1"
13+
"apollo-server-express": "^2.12.0",
14+
"apollo-server-plugin-response-cache": "^0.4.1",
15+
"cors": "^2.8.5",
16+
"deepmerge": "^4.2.2",
17+
"express": "^4.17.1",
18+
"graphql": "^15.0.0"
19+
},
20+
"devDependencies": {
21+
"eslint": "^6.8.0",
22+
"eslint-config-airbnb-base": "^14.1.0"
1423
}
1524
}

readme.md

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,32 @@
1-
# nrdcp API
1+
# nrdcp GraphQL API
22

3-
## endpoints
4-
5-
### /v1/home-sensor/latest
6-
7-
## setting up
3+
## credentials
84

95
check correct project is set with `gcloud config list project`
106
if not, update with `export GOOGLE_CLOUD_PROJECT=$(gcloud config get-value core/project)`
117

128
associate with service account (needs at least BigQuery User and Viewer permissions)
139
`export GOOGLE_APPLICATION_CREDENTIALS=/Users/${USER}/gcp/keys/big-query-api-key.json`
1410

11+
## run locally
12+
1513
install dependencies `npm install`
14+
run server `npm start`
15+
navigate to `http://localhost:8080/graphql`
16+
17+
## available data
18+
19+
latest Home Sensor reading (SQL query directly on BiqQuery)
20+
21+
```
22+
query {
23+
latestSensorReading {
24+
temperature,
25+
humidity,
26+
timestamp
27+
}
28+
}
29+
```
1630

1731
## build image
1832

@@ -30,12 +44,10 @@ gcloud run deploy nrdcp-api \
3044
--allow-unauthenticated
3145
```
3246

33-
## todo
47+
## TODO
3448

35-
* explore cloudbuild config
36-
* cors
37-
* git
38-
* logging
49+
* Logging
50+
* Cloudbuild from git hash
3951

4052

4153

src/data-sources/home-sensor.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
const { BigQuery } = require('@google-cloud/bigquery');
2+
3+
class HomeSensorAPI {
4+
constructor() {
5+
this.bigqueryClient = new BigQuery();
6+
}
7+
8+
async getLatestReading() {
9+
const sqlQuery = `SELECT
10+
temp as temperature,
11+
humd as humidity,
12+
UNIX_MILLIS(TIMESTAMP(time)) as timestamp
13+
FROM pi3_dht22_dataset.dht22_data tbl
14+
ORDER BY tbl.time DESC
15+
LIMIT 1`;
16+
17+
const queryOptions = {
18+
query: sqlQuery,
19+
location: 'US',
20+
};
21+
22+
const [rows] = await this.bigqueryClient.query(queryOptions);
23+
24+
return({
25+
data: rows[0],
26+
});
27+
}
28+
}
29+
30+
module.exports.HomeSensorAPI = HomeSensorAPI;

src/data-sources/index.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
2+
const { HomeSensorAPI } = require('./home-sensor');
3+
4+
const getDataSources = () => ({
5+
homeSensorAPI: new HomeSensorAPI(),
6+
});
7+
8+
module.exports.getDataSources = getDataSources;

src/graphql-modules/home-sensor.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
const { gql } = require('apollo-server-express');
2+
3+
const typeDefs = gql`
4+
extend type Query {
5+
latestSensorReading: SensorReading!,
6+
}
7+
8+
type SensorReading {
9+
temperature: String,
10+
humidity: String,
11+
timestamp: Float,
12+
}
13+
`;
14+
15+
const resolvers = {
16+
Query: {
17+
latestSensorReading: async (parent, args, { dataSources }, info) => {
18+
info.cacheControl.setCacheHint({ maxAge: 300, scope: 'PUBLIC' });
19+
20+
const response = await dataSources.homeSensorAPI.getLatestReading();
21+
22+
return response.data || {};
23+
},
24+
},
25+
};
26+
27+
module.exports = {
28+
typeDefs,
29+
resolvers,
30+
};

src/graphql-modules/index.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
const deepmerge = require('deepmerge');
2+
const { gql } = require('apollo-server-express');
3+
4+
const {
5+
resolvers: homeSensorResolvers,
6+
typeDefs: homeSensorTypeDefs,
7+
} = require('./home-sensor');
8+
9+
const queryTypeDefs = gql`
10+
type Query {
11+
_empty: String
12+
}
13+
`;
14+
15+
module.exports = {
16+
typeDefs: [queryTypeDefs, homeSensorTypeDefs],
17+
resolvers: deepmerge({}, homeSensorResolvers),
18+
};

src/home-sensor.js

Lines changed: 0 additions & 31 deletions
This file was deleted.

src/index.js

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,30 @@
11
const express = require('express');
2-
const apicache = require('apicache');
2+
const cors = require('cors');
3+
const responseCachePlugin = require('apollo-server-plugin-response-cache');
4+
const { ApolloServer } = require('apollo-server-express');
35

4-
const { homeSensorLatestHandler } = require('./home-sensor');
6+
const { getDataSources } = require('./data-sources');
7+
const { typeDefs, resolvers } = require('./graphql-modules');
58

69
const app = express();
7-
const cache = apicache.middleware;
810

911
app.get('/', (req, res) => {
1012
res.send('api I am');
1113
});
1214

13-
app.get('/v1/home-sensor/latest', cache('10 minutes'), homeSensorLatestHandler);
14-
1515
const port = process.env.PORT || 8080;
1616

17+
const apollo = new ApolloServer({
18+
typeDefs,
19+
resolvers,
20+
dataSources: getDataSources,
21+
plugins: [responseCachePlugin()],
22+
});
23+
24+
app.use(cors());
25+
26+
apollo.applyMiddleware({ app, path: '/graphql' });
27+
1728
app.listen(port, () => {
1829
console.log('Listening on port', port);
1930
});

0 commit comments

Comments
 (0)