npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@lukinco/adonis-apollo-server

v0.2.0

Published

Production-ready Node.js GraphQL server for AdonisJS

Downloads

11

Readme

adonis-apollo-server

GraphQL implementation using Apollo Server for Adonis

This package integrates Apollo GraphQL Server with the AdonisJS framework. It allows you to use Apollo server in your AdoinsJS app.

NOTE: This package requires @adonisjs/bodyparser and graphql

Installation

yarn add --exact @lukinco/adonis-apollo-server

Registering provider

Make sure to register the provider inside start/app.js file.

const providers = [
  '@lukinco/adonis-apollo-server/providers/ApolloServerProvider'
]

That's all!

Usage

Now you can use the provider by pulling it from IoC container

// start/routes.js

'use strict'

const Route = use('Route')
const ApolloServer = use('ApolloServer')

const typeDefs = `
  type Query {
    testString: String
  }
`

const resolvers = {
  Query: {
    testString () {
      return 'Seems to be working!'
    }
  }
}

const schema = { typeDefs, resolvers }

Route.post('/graphql', ({ auth, request, response }) => {
  return ApolloServer.graphql({ 
    options: {
      schema,
      context: { auth }
    },
    request, 
    response,
    onError: (errors) => {
      // this function is optional. "errors" is an array of all errors. 
      // You may show the errors the way you want to.
      // If this function is defined, you must return an array of errors.
    }
  })
})

Route.get('/graphiql', ({ request, response }) => {
  return ApolloServer.graphiql({
    options: { endpointURL: '/graphql' }, 
    request, 
    response
  })
})

Uploads

To make uploads, you must set autoProcess: false on config/bodyParser.js.

You must define the field that will receive the uploaded file with scalar type Upload:

type Mutation {
  upload (file: Upload!): String
}

Usage

You may create a helper file in app/Helpers/upload.js:

'use strict'

const fs = require('fs')
const { join } = require('path')
const slugify = require('slugify')
const { v4: uuidv4 } = require('uuid')
const Env = use('Env')

const UPLOAD_DIRNAME = 'uploads'
const FULL_UPLOAD_PATH = join(process.cwd(), 'public', UPLOAD_DIRNAME)

fs.mkdir(FULL_UPLOAD_PATH, { recursive: true }, () => {})

module.exports = async (file) => {
  const { createReadStream, filename } = await file
  const fileStream = createReadStream()
  const newFilename = `${uuidv4()}-${slugify(filename, { lower: true })}`

  const pathToUploadFile = join(FULL_UPLOAD_PATH, newFilename)
  const uploadDistStream = fs.createWriteStream(pathToUploadFile)

  await new Promise((resolve, reject) => {
    uploadDistStream.on('finish', resolve)

    uploadDistStream.on('error', (error) => {
      console.log('error', error)
      fs.unlink(pathToUploadFile, () => reject(error))
    })

    fileStream.on('error', (error) => uploadDistStream.destroy(error))

    fileStream.pipe(uploadDistStream)
  })

  return `${Env.get('UPLOAD_HOST')}/${UPLOAD_DIRNAME}/${newFilename}`
}

Libs slugify and uuid are optional, but they will help you to create unique filenames.

You can use an env var UPLOAD_HOST, like my example, if you want to upload files in different places by environment.

Then, when you want to make an upload, you just have to use that function, passing the file received as argument, and the function will return a Promise, that resolves to a full path of the file uploaded.

To send a file, look the next examples.

How to test using Insomnia

On Insomnia, you must use Multipart requests, and send 3 fields:

  • operations: a JSON with query and variables keys:
{
  "query": "mutation ($file: Upload!) {\n  upload (file: $file) \n}",
  "variables": {
    "file": null
  }
}
  • map: a JSON mapping the file that will be upload with your variables set in operations:
{
  "0": ["variables.file"]
}
  • 0: the file itself. 0 is used here because we set in map above that 0 will point to our variables.file entry.

That's it :)

How to write tests

In Adonis v4, you have to install axios and form-data libraries to make the upload work on server side.

Then, you can use a helper to upload file like this:

const fs = require('fs')
const gql = require('graphql-tag')
const { print } = require('graphql/language/printer')
const axios = require('axios')
const FormData = require('form-data')
const Env = use('Env')

async function requestQuery ({ client, token, query, variables, file }) {
  if (token) {
    response = response.header('Authorization', `Bearer ${token}`)
  }

  const operations = {
    query: print(query),
    variables,
  }

  file = typeof file === 'string'
    ? { field: 'file', attach: file }
    : file

  const variableInput = Object.keys(variables)[0] === file.field
    ? `${file.field}`
    : `${Object.keys(variables)[0]}.${file.field}`

  const map = {
    0: [`variables.${variableInput}`],
  }

  const form = new FormData()
  form.append('operations', JSON.stringify(operations))
  form.append('map', JSON.stringify(map))
  form.append('0', fs.createReadStream(file.attach))

  return axios
    .post(`${Env.get('APP_URL')}/graphql`, form, {
      headers: {
        authorization: `Bearer ${token}`,
        ...form.getHeaders(),
      },
    })
}

Then, just write your test:

const fs = require('fs')
const { test, trait } = use('Test/Suite')('Upload')
const Helpers = use('Helpers')
const gql = require('graphql-tag')
const { expect } = require('chai')

trait('Test/ApiClient')
trait('Auth/Client')

const UPLOAD = gql`
  mutation ($file: Upload!) {
    upload (file: $file) {
      location
    }
  }
`

test('Should upload an image with mimetype PNG', async ({ client }) => {
  const file = Helpers.tmpPath('file.png')
  fs.writeFile(file, 'TEST', () => {})

  const response = await requestQuery({
    client,
    token, // use a token if you only want allow uploads for logged in users
    query: UPLOAD,
    variables: { file: null },
    file,
  })

  const result = response.data

  expect(response.status).to.be.equal(200)
  expect(result).to.have.keys('data')
  expect(result.data).to.have.keys(['upload'])
  expect(result.data.upload).to.be.a('string')
})

License

MIT