Skip to content

Commit eaf633e

Browse files
authored
Merge pull request #166 from neo4j/updates-for-ogm-installation-page
Updates for ogm installation page
2 parents 4e5f7e2 + 94d769d commit eaf633e

File tree

1 file changed

+84
-65
lines changed

1 file changed

+84
-65
lines changed

modules/ROOT/pages/ogm/installation.adoc

Lines changed: 84 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
[[ogm-installation]]
2-
:description: This page describes how to install the OGM in Neo4j GraphQL and includes examples of how to use it.
2+
:description: This page describes how to install the OGM in Neo4j GraphQL and how to use it.
33
= Installation
44
:page-aliases: ogm/examples/index.adoc
55

6-
The OGM can be installed into a new or existing Node.js project in a similar way to the installation of the Neo4j GraphQL Library.
7-
As such, it requires some dependencies to be included:
6+
You can install the OGM into a new or existing Node.js project in a similar way to how you install the Neo4j GraphQL Library.
7+
It has the following dependencies:
88

99
* `@neo4j/graphql-ogm`: the OGM package.
1010
* `graphql`: the package used by the Neo4j GraphQL Library to generate a schema and execute queries and mutations.
@@ -15,54 +15,49 @@ As such, it requires some dependencies to be included:
1515
npm install @neo4j/graphql-ogm graphql neo4j-driver
1616
----
1717

18-
To use the OGM, you must always import it:
19-
20-
[source, javascript, indent=0]
21-
----
22-
const { OGM } = require("@neo4j/graphql-ogm");
23-
----
2418

2519
== Usage examples
2620

27-
Here are some examples of how you might take advantage of the OGM.
21+
Here are some examples of how you can use the OGM.
2822

2923
[[ogm-examples-custom-resolvers]]
3024
=== Custom Resolvers
3125

32-
A common case for using the OGM will be within custom resolvers inside a Neo4j GraphQL instance (very meta!), due to the fact that it has access to some fields which the Neo4j GraphQL Library may not. A common use case might be to have a `password` field marked with directive `@private`, and a custom resolver for creating users with passwords.
26+
The OGM has access to some fields which the Neo4j GraphQL Library doesn't.
27+
It is common practice to use the OGM to create custom resolvers when dealing with such fields.
28+
For example, you can have a `password` field marked with the `@private` directive and a custom resolver for creating users with passwords.
3329

34-
To get started with this example, create your example application directory, create a new project and also the file which will contain your application code:
30+
Execute the following to create an example application directory and create a new project:
3531

3632
[source, bash, indent=0]
3733
----
3834
mkdir ogm-custom-resolvers-example
3935
cd ogm-custom-resolvers-example
40-
npm init --yes
36+
npm init es6 --yes
4137
touch index.js
4238
----
4339

44-
Then you need to install your dependencies:
40+
Install the dependencies:
4541

4642
[source, bash, indent=0]
4743
----
48-
npm install @neo4j/graphql-ogm graphql neo4j-driver apollo-server
44+
npm install @neo4j/graphql-ogm graphql neo4j-driver @apollo/server
4945
----
5046

51-
Assuming a running Neo4j database at "bolt://localhost:7687" with username "neo4j" and password "password", in your empty `index.js` file, add the following code:
47+
Assuming a running Neo4j database at "neo4j://localhost:7687" with username "username" and password "password", in your empty `index.js` file, add the following code:
5248

5349
[source, javascript, indent=0]
5450
----
5551
import { ApolloServer } from "@apollo/server";
5652
import { startStandaloneServer } from "@apollo/server/standalone";
57-
import { Neo4jGraphQLAuthJWTPlugin } from "@neo4j/graphql-plugin-auth";
5853
import { Neo4jGraphQL } from "@neo4j/graphql";
5954
import { OGM } from "@neo4j/graphql-ogm";
6055
import neo4j from "neo4j-driver";
6156
62-
import { createJWT, comparePassword } from "./utils"; // example util function, more information below
57+
import { createJWT, comparePassword } from "./utils.js"; // example util function, more information below
6358
6459
const driver = neo4j.driver(
65-
"bolt://localhost:7687",
60+
"neo4j://localhost:7687",
6661
neo4j.auth.basic("username", "password")
6762
);
6863
@@ -106,55 +101,73 @@ const resolvers = {
106101
107102
return createJWT({ sub: users[0].id });
108103
},
104+
109105
signIn: async (_source, { username, password }) => {
110106
const [user] = await User.find({
111107
where: {
112108
username,
113109
},
114110
});
115-
111+
116112
if (!user) {
117113
throw new Error(`User with username ${username} not found!`);
118114
}
119115
120116
const correctPassword = await comparePassword(password, user.password);
121117
122118
if (!correctPassword) {
123-
throw new Error(`Incorrect password for user with username ${username}!`);
119+
throw new Error(
120+
`Incorrect password for user with username ${username}!`
121+
);
124122
}
125123
126124
return createJWT({ sub: user.id });
127125
},
128126
},
129127
};
130128
129+
131130
const neoSchema = new Neo4jGraphQL({
132131
typeDefs,
133132
driver,
134133
resolvers,
135-
plugins: {
136-
auth: new Neo4jGraphQLAuthJWTPlugin({
137-
secret: "secret"
138-
})
139-
}
134+
features: {
135+
authorization: {
136+
key: "secret",
137+
},
138+
},
140139
});
141140
142-
Promise.all([neoSchema.getSchema(), ogm.init()]).then(([schema]) => {
141+
async function main() {
142+
await ogm.init();
143+
143144
const server = new ApolloServer({
144-
schema,
145+
schema: await neoSchema.getSchema(),
145146
});
146147
147-
startStandaloneServer(server, {
148-
context: async ({ req }) => ({ req }),
149-
}).then(({ url }) => {
150-
console.log(`🚀 Server ready at ${url}`);
148+
const { url } = await startStandaloneServer(server, {
149+
listen: { port: 4000 },
150+
context: async ({ req }) => ({
151+
token: req.headers.authorization,
152+
}),
151153
});
152-
});
154+
155+
console.log(`🚀 Server ready at ${url}`);
156+
}
157+
158+
main();
153159
----
154160

155-
It's important to note the JWT secret being passed into the `Neo4jGraphQL` constructor in this example.
161+
Create the file `utils.js` in the same directory.
162+
Install additional dependencies:
163+
164+
[source, bash, indent=0]
165+
----
166+
npm install bcrypt jsonwebtoken
167+
----
168+
169+
Add the following code to `utils.js`:
156170

157-
Additionally, an example implementation for the util functions `createJWT` and `comparePassword` is provided in this code snippet:
158171
[source, javascript, indent=0]
159172
----
160173
import bcrypt from "bcrypt";
@@ -167,7 +180,7 @@ export function createJWT(data) {
167180
return reject(err);
168181
}
169182
170-
return resolve(token as string);
183+
return resolve(token);
171184
});
172185
});
173186
}
@@ -187,11 +200,11 @@ export function comparePassword(plainText, hash) {
187200

188201
[NOTE]
189202
====
190-
This code for the util functions `createJWT` and `comparePassword` is an example.
191-
You will likely need to adjust it to suit your use case.
203+
The code for the util functions `createJWT` and `comparePassword` is an example.
204+
Adjust it to suit your use case.
192205
====
193206

194-
Back in the command line, run the following command to start your server:
207+
Back on the command line, run the following command to start your server:
195208

196209
[source, bash, indent=0]
197210
----
@@ -205,31 +218,32 @@ You should see the following output:
205218
🚀 Server ready at http://localhost:4000/
206219
----
207220

208-
You can execute the `signUp` Mutation against this GraphQL API to sign up, but when you go to query the user through the same API, the password field will not be available.
221+
You can execute the `signUp` mutation against the GraphQL API to sign up, but if you try querying the user through the same API, the password field will not be available.
209222

210223
[[ogm-examples-rest-api]]
211224
=== REST API
212225

213-
This example demonstrates how you might use the OGM without exposing a Neo4j GraphQL API endpoint. The example starts an https://expressjs.com/[Express] server and uses the OGM to interact with the Neo4j GraphQL Library, exposed over a REST endpoint.
226+
This example demonstrates how you can use the OGM without exposing a Neo4j GraphQL API endpoint.
227+
It starts an https://expressjs.com/[Express] server and uses the OGM to interact with the Neo4j GraphQL Library, exposed via a REST endpoint.
214228

215-
First, create your example application directory, create a new project and also the file which will contain yur application code:
229+
Execute the following to create an example application directory and a new project:
216230

217231
[source, bash, indent=0]
218232
----
219233
mkdir ogm-rest-example
220234
cd ogm-rest-example
221-
npm init --yes
235+
npm init es6 --yes
222236
touch index.js
223237
----
224238

225-
Then you need to install your dependencies:
239+
Install the dependencies:
226240

227241
[source, bash, indent=0]
228242
----
229243
npm install @neo4j/graphql-ogm graphql neo4j-driver express
230244
----
231245

232-
Assuming a running Neo4j database at "bolt://localhost:7687" with username "neo4j" and password "password", in your empty `index.js` file, add the following code:
246+
Assuming a running Neo4j database at "neo4j://localhost:7687" with username "username" and password "password", in your empty `index.js` file, add the following code:
233247

234248
[source, javascript, indent=0]
235249
----
@@ -238,8 +252,8 @@ import { OGM } from "@neo4j/graphql-ogm";
238252
import neo4j from "neo4j-driver";
239253
240254
const driver = neo4j.driver(
241-
"bolt://localhost:7687",
242-
neo4j.auth.basic("username", "password")
255+
"bolt://localhost:7687",
256+
neo4j.auth.basic("username", "password")
243257
);
244258
245259
const typeDefs = `
@@ -249,34 +263,39 @@ const typeDefs = `
249263
}
250264
`;
251265
252-
const ogm = new OGM({ typeDefs, driver });
266+
const ogm = new OGM({
267+
typeDefs,
268+
driver,
269+
features: { filters: { String: { MATCHES: true } } },
270+
});
271+
253272
const User = ogm.model("User");
254273
255274
const app = express();
256275
257276
app.get("/users", async (req, res) => {
258-
const { search, offset, limit, sort } = req.query;
277+
const { search, offset, limit, sort } = req.query;
259278
260-
const regex = search ? `(?i).*${search}.*` : null;
279+
const regex = search ? `(?i).*${search}.*` : null;
261280
262-
const users = await User.find({
263-
where: { name_REGEX: regex },
264-
options: {
265-
offset,
266-
limit,
267-
sort
268-
}
269-
});
281+
const users = await User.find({
282+
where: { name_MATCHES: regex },
283+
options: {
284+
offset,
285+
limit,
286+
sort,
287+
},
288+
});
270289
271-
return res.json(users).end();
290+
return res.json(users).end();
272291
});
273292
274293
const port = 4000;
275294
276295
ogm.init().then(() => {
277-
app.listen(port, () => {
278-
console.log("Example app listening at http://localhost:${port}")
279-
});
296+
app.listen(port, () => {
297+
console.log(`Example app listening at http://localhost:${port}/users`);
298+
});
280299
});
281300
----
282301

@@ -287,11 +306,11 @@ In your application directory, you can run this application:
287306
node index.js
288307
----
289308

290-
Which should output:
309+
You should see the following output:
291310

292311
[source, bash, indent=0]
293312
----
294-
Example app listening at http://localhost:4000
313+
Example app listening at http://localhost:4000/users
295314
----
296315

297-
The REST API should now be ready to accept requests at the URL logged.
316+
The REST API should now be available at `http://localhost:4000`, with a single working route `/users`.

0 commit comments

Comments
 (0)