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

Include working example of running a server #2373

Open
4 of 6 tasks
derekjwilliams opened this issue Feb 17, 2025 · 7 comments
Open
4 of 6 tasks

Include working example of running a server #2373

derekjwilliams opened this issue Feb 17, 2025 · 7 comments

Comments

@derekjwilliams
Copy link

derekjwilliams commented Feb 17, 2025

Feature description

It would be great if the documentation had a working example of running a server

Here is an example:

Create a simple node project and install packages

  mkdir postgraphile_v5_node_example
  cd postgraphile_v5_node_example
  npm init -y
  npm install -D @tsconfig/node20 @types/express @types/node typescript
  npm install express postgraphile@beta

Add start script to package.json

  "scripts": {
    "start": "GRAPHILE_ENV=development node --experimental-strip-types --watch index.ts"
  },

Create or modify tsconfig.json to

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "nodenext"
  }
}

Create a simple server in typescript

Create index.ts with these contents

import express from "express";
import { createServer } from "node:http";
import { postgraphile } from "postgraphile";
import { makePgService } from "postgraphile/adaptors/pg";
import { grafserv } from "postgraphile/grafserv/express/v4";
import { PostGraphileAmberPreset } from "postgraphile/presets/amber";

/** @type {GraphileConfig.Preset} */
const preset = {
  extends: [PostGraphileAmberPreset],
  pgServices: [
    makePgService({
      connectionString: "postgres://yourusername:yourpossword@localhost:5432/yourdatabase",
      schemas: ["public"], // change schema here if needed
    }),
  ],
  grafast: {
    explain: true,
  },
};
(async () => {
  const app = express();
  const server = createServer(app);
  server.on("error", (e) => {
    console.dir(e);
  });
  const pgl = postgraphile(preset);
  const serv = pgl.createServ(grafserv);
  await serv.addTo(app, server);
  server.listen(5050, () => {
    console.log("Server listening at http://localhost:5050");
  })
})();

Run from command line and open GraphiQL UI

npm run start

Open browser and navigate to http://localhost:5050 to view the GraphiQL UI

Motivating example

Could not find any working examples in documentation

Breaking changes

None

Supporting development

  • am interested in building this feature myself
  • am interested in collaborating on building this feature
  • am willing to help testing this feature before it's released
  • am willing to write a test-driven test suite for this feature (before it exists)
  • am a Graphile sponsor ❤️
  • have an active support or consultancy contract with Graphile
@github-project-automation github-project-automation bot moved this to 🌳 Triage in V5.0.0 Feb 17, 2025
@benjie
Copy link
Member

benjie commented Feb 17, 2025

I agree: we should definitely have fully working examples in the docs! Please could you explain how the examples on the usage page fall short of this desire? Since you're interested in contributing - please feel free to raise pull requests directly against that page using the "Edit this page" link on the page ❤

(As an additional resource, check out ouch-my-finger which is mostly used for debugging)

@derekjwilliams
Copy link
Author

derekjwilliams commented Feb 17, 2025

Thanks so much, I really appreciate the work that you do, and for getting back so quickly.

The challenges that I faced were finding the correct combination of pgl.js contents, graphile.config.mjs (or graphile.config.ts), and example-node.js vs example-express.js. In addition, I had to find the correct npm modules to import.

So it may be as easy as creating a section in the documentation dedicated to a simple working example. I would be happy to put that into a PR. Having the example in the code repository may also be helpful.

Maybe something like:

A Simple Working Express Application Example With Three Files

Create and Initialize a Project:

  mkdir postgraphile_v5_node_express_example
  cd postgraphile_v5_node_express_example
  npm init -y
  npm install -D @tsconfig/node20 @types/express @types/node typescript
  npm install express postgraphile@beta

The Three files

The three files in this example are server.js, pgl.js, and graphile.config.mjs.

server.js Express Server

//server.js
import { createServer } from "node:http";
import express from "express";
import { grafserv } from "postgraphile/grafserv/express/v4";
import { pgl } from "./pgl.js";

const serv = pgl.createServ(grafserv);

const app = express();
const server = createServer(app);
server.on("error", () => {});
serv.addTo(app, server).catch((e) => {
  console.error(e);
  process.exit(1);
});
server.listen(5678);

console.log("Server listening at http://localhost:5678");

pgl.js Get PostGraphile Instance

//pgl.js
import preset from "./graphile.config.mjs";
import { postgraphile } from "postgraphile";

// Our PostGraphile instance:
export const pgl = postgraphile(preset);

graphile.config.mjs Configuration

//graphile.config.mjs
import { PostGraphileAmberPreset } from "postgraphile/presets/amber";
import { makePgService } from "postgraphile/adaptors/pg";

/** @type {GraphileConfig.Preset} */
const preset = {
  extends: [PostGraphileAmberPreset],
  pgServices: [makePgService({connectionString: 'postgres://your_username:your_password@localhost:5432/your_database', schemas: ["public"]})],
};

export default preset;

Replace your_username, your_password, and your_database with values for your PostgreSQL database. Replace public with your schema, if it is not public. And change the port if you are not using 5432

Add start to package.json

Your package.json should look like this

{
  "scripts": {
    "start": "GRAPHILE_ENV=development node --watch server.js",
   },
  "type": "module",
  "devDependencies": {
    "@tsconfig/node20": "^20.1.4",
    "@types/express": "^5.0.0",
    "@types/node": "^20.11.24",
    "typescript": "^5.7.3"
  },
  "dependencies": {
    "express": "^4.21.2",
    "postgraphile": "^5.0.0-beta.38"
  }
}

Newer versions of those packages will likely also work.

Start the server at the command line npm run start. Open a browser to http://localhost:5678 to see the GraphiQL user interface.

[Maybe an image here]

One nice thing about starting with a single file is that it is very clear that only that file is needed. Using multiple files is great to separate concerns but for someone new to this version of Postgraphile it took quite a while to figure out.


More about steps I took,

I started with the usage page, but when I tried putting together a simple working server I ran into issues, mostly around not seeing which files were needed.

For instance I got a bit tripped up on this sentence,

"Library mode is configured using a preset (see Configuration for the options) and returns a PostGraphile instance pgl which has various methods you can use depending on what you're trying to do."

Which means (clearly now) that the user needs to create a graphile.config.js file (for example). The example pgl.js is importing from js graphile.config.js not mjs. I tried using the graphile.config.js file on the Configuration page, that file is in this section. Using that file does not work for a simple example, returns errors when running; it is obvious now that that is not the correct file for a simple example, the graphile.config.mjs on the Configuration page is correct (but missing the connection string) so the import needed to be adjusted in pgl.js to import preset from "./graphile.config.mjs";

I copied the example-express.js code, and pgl.js from the usage page. I then copied the graphile.config.mjs from the Configuration documentation. That file is missing the connection string, so I added makePgService with my connection string, for example:

import { PostGraphileAmberPreset } from "postgraphile/presets/amber";
import { makePgService } from "postgraphile/adaptors/pg";

/** @type {GraphileConfig.Preset} */
const preset = {
  extends: [PostGraphileAmberPreset],
  pgServices: [makePgService({connectionString: 'postgres://postgres:postgres@localhost:5432/events', schemas: ["public"]})],
};

export default preset;

And then it worked.

@benjie
Copy link
Member

benjie commented Feb 17, 2025

Really really valuable commentary; thanks!

Please go ahead and make the changes that you see fit on whichever pages make sense to do so. You may also want to check on the quick start guide.

V5 documentation is still very much work in progress, and some of it is probably even wrong due to API changes having happened since the original docs were written - I'll definitely be going over it carefully when V5 hits release candidate status, but for now I'm relying on folks like yourself to help keep it correct by spotting and fixing errors and ideally monitoring the changelogs for breaking changes and making sure the documentation is updated. I'm currently focussed on #2060 which is humongous (multi-month project) and am trying to stay focused to keep moving us towards RC status 🚀

@benjie
Copy link
Member

benjie commented Feb 17, 2025

Also: taking notes like you have done above in issues when something is non obvious is the absolute best thing to do. It's very hard to figure out why you were confused once something makes sense, best to share early that you're confused and then track your progress so that the docs can be improved for future readers - exactly as you have done! 🙌

@github-project-automation github-project-automation bot moved this from 🌳 Triage to ✅ Done in V5.0.0 Feb 19, 2025
@benjie
Copy link
Member

benjie commented Feb 19, 2025

Let's leave this open until the docs have been improved; don't want to lose track of your valuable content!

@benjie benjie reopened this Feb 19, 2025
@github-project-automation github-project-automation bot moved this from ✅ Done to 🌱 In Progress in V5.0.0 Feb 19, 2025
@derekjwilliams
Copy link
Author

Thanks, I'll work on a PR this evening

@derekjwilliams
Copy link
Author

PR has been created, it has examples for both JavaScript and TypeScript, I believe that the steps to create working servers with the two approaches are complete. The updates have the complete contents of the JavaScript files, TypeScript files, .env, package.json, and tsconfig.js.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: 🌱 In Progress
Development

No branches or pull requests

2 participants