🪅 Nuxt 3 module to connect with any API securely – server proxy & customizable composable names

Overview

nuxt-api-party

npm version

This module provides composables to fetch data from an API of your choice securely.

You can customize the composable names! Given json-placeholder set as the module option name in your Nuxt config, the composables $jsonPlaceholder and useJsonPlaceholderData will be available globally.

Features

  • 🪅 Dynamic composable names
  • 🔒 Protect your API credentials in the client
  • 🪢 Token-based authentication built-in or bring your own headers
  • 🍱 Handle request similar to useFetch
  • 🗃 Cached responses
  • 🦾 Strongly typed

Setup

# pnpm
pnpm add -D nuxt-api-party

# npm
npm i -D nuxt-api-party

How It Works

Composables will initiate a POST request to the Nuxt server route /api/__api_party__, which then fetches the actual data for a given route from your API and passes the response back to the template/client. This proxy behaviour has the benefit of omitting CORS issues, since data is sent from server to server.

During server-side rendering, calls to the Nuxt server route will directly call the relevant function (emulating the request), saving an additional API call.

ℹ️ Responses are cached and hydrated to the client. Subsequent calls will return cached responses, saving duplicated requests.

Basic Usage

Add nuxt-api-party to your Nuxt config and tell the module options the name of your API:

// `nuxt.config.ts`
export default defineNuxtConfig({
  modules: ['nuxt-api-party'],

  apiParty: {
    // Needed for the names of the composables
    name: 'json-placeholder'
  }
})

Set the following environment variables in your project's .env file:

API_PARTY_BASE_URL=https://jsonplaceholder.typicode.com
# Optionally, add a bearer token
# API_PARTY_TOKEN=test

If you were to call your API json-placeholder, the generated composables are:

  • $jsonPlaceholder – Returns the response data, similar to $fetch
  • useJsonPlaceholderData – Returns multiple values similar to useFetch

Finally, fetch data from your API in your template:

<script setup lang="ts">
interface Post {
  userId: number
  id: number
  title: string
  body: string
}

// `data` will be typed as `Ref<Post | null>`
const { data, pending, refresh, error } = await useJsonPlaceholderData<Post>('posts/1')
</script>

<template>
  <div>
    <h1>{{ data?.title }}</h1>
    <pre>{{ JSON.stringify(data, undefined, 2) }}</pre>
  </div>
</template>

Composables

ℹ️ The headings of the following sections aren't available as-is. As an example, the module option name is set to party.

$party

Returns the API response data.

Types

function $party<T = any>(
  path: string,
  opts: ApiFetchOptions = {},
): Promise<T>

type ApiFetchOptions = Pick<
  FetchOptions,
  'onRequest' | 'onRequestError' | 'onResponse' | 'onResponseError' | 'headers'
>

Example

<script setup lang="ts">
const data = await $party(
  'posts/1',
  {
    async onRequest({ request }) {
      console.log(request)
    },
    async onResponse({ response }) {
      console.log(response)
    },
    async onRequestError({ error }) {
      console.log(error)
    },
    async onResponseError({ error }) {
      console.log(error)
    },
  }
)
</script>

<template>
  <div>
    <h1>{{ data?.title }}</h1>
  </div>
</template>

usePartyData

Return values:

  • data: the response of the API request
  • pending: a boolean indicating whether the data is still being fetched
  • refresh: a function that can be used to refresh the data returned by the handler function
  • error: an error object if the data fetching failed

By default, Nuxt waits until a refresh is finished before it can be executed again. Passing true as parameter skips that wait.

Types

export function usePartyData<T = any>(
  path: MaybeComputedRef<string>,
  opts: UseApiDataOptions<T> = {},
): AsyncData<T, FetchError | null | true>

type UseApiDataOptions<T> = Pick<
  UseFetchOptions<T>,
  // Pick from `AsyncDataOptions`
  | 'lazy'
  | 'default'
  | 'watch'
  | 'initialCache'
  | 'immediate'
  // Pick from `FetchOptions`
  | 'onRequest'
  | 'onRequestError'
  | 'onResponse'
  | 'onResponseError'
  // Pick from `globalThis.RequestInit`
  | 'headers'
>

The composable infers most of the useAsyncData options.

Example

<script setup lang="ts">
const { data, pending, error, refresh } = await usePartyData('posts/1')
</script>

<template>
  <div>
    <h1>{{ data?.result?.title }}</h1>
    <button @click="refresh()">
      Refresh
    </button>
  </div>
</template>

💻 Development

  1. Clone this repository
  2. Enable Corepack using corepack enable (use npm i -g corepack for Node.js < 16.10)
  3. Install dependencies using pnpm install
  4. Run pnpm run dev:prepare
  5. Start development server using pnpm run dev

Special Thanks

License

MIT License © 2022 Johann Schopplich

Comments
  • Support `FormData` proxy to API endpoint

    Support `FormData` proxy to API endpoint

    I'm writing a simple page for uploading files, when using normal $fetch everything works fine, but after switching to api-party, it doesn't work and I get an error: Unknown object type "formdata".

    Minimal Reproduction:

    <template>
      <main>
        <input ref="schematicFile" accept=".schematic,.schem,.litematic" type="file" @change="onSchematicFileChanged($event)"/>
      </main>
    </template>
    
    <script setup lang="ts">
    const schematicFile = ref<File | null>()
    const uploading = ref(false)
    const progress = ref(0.0)
    
    interface uploadResponse {
      download_key: String,
      delete_key: String,
    }
    
    const onSchematicFileChanged = ($event: Event) => {
      const target = $event.target as HTMLInputElement
      if (target && target.files) {
        schematicFile.value = target.files[0]
        uploadSchematic()
      }
    }
    
    const uploadSchematic = async () => {
      if (!schematicFile.value) {
        return
      }
    
      uploading.value = true
    
      const formData = new FormData()
      formData.append('schematic', schematicFile.value as Blob)
    
      // const resp = await $uploadApi<uploadResponse>('upload', {
      const resp = await $fetch<uploadResponse>('https://ark.sunxyw.xyz/upload', {
        method: 'POST',
        body: formData,
      })
      console.log(resp)
    }
    </script>
    
    opened by sunxyw 8
  • How to inspect API response error

    How to inspect API response error

    Hey and thanks for your awesome nuxt module! I really like it.

    Unfortunately, I have a small problem that I can not solve. No matter what status code I get back from my API. It always returns the error code 500. Is there a way to get the correct status code?

    POST http://localhost:3000/api/__api_party/cms 500 (Failed to fetch from API endpoint "cms")

    But the correct status code should be 400

    opened by Robinrrr 5
  • Support for payload methods

    Support for payload methods

    Hello I'm looking at this module and it seems exactly like something I could use for my project. Looking at the code though it doesn't seem like it's possible to perform any other request methods than 'GET' requests. Is this something that will be added in the near feature? Otherwise this module looks very nice. Amazing work!

    opened by itm-ape 3
  • Typings for `apiParty` seem to be missing in `nuxt.config.ts`

    Typings for `apiParty` seem to be missing in `nuxt.config.ts`

    Hi,

    After installing api party and adding it to the modules, it seems that 'apiParty' isn't being recognised in nuxt.config.ts. It gives the following message: "Object literal may only specify known properties, and 'apiParty' does not exist in type 'NuxtConfig'."

    image

    opened by Luuk 2
  • Adding URL params to API Party config

    Adding URL params to API Party config

    Hi,

    I would like to add url params to my API Party config as these are required for my API to authenticate. However, I cannot find a way to include the ?api_key param at the end of url.

    Format I need: API_PARTY_BASE_URL + PATH + URL_PARAMS Example: https://api.themoviedb.org/3/movie/550?api_key=xxxxxxxxxxxxx

    opened by Luuk 1
  • Support for errors in apis

    Support for errors in apis

    Hey! :D

    I tried using the module and i noticed that when im returning an error code to the api for example 422 when a validator on the server fails,the error stack is not accessable and i cant show the error to the user.

    For example: {"url":"/api/__api_party/api","statusCode":500,"statusMessage":"Failed to fetch from API endpoint \"api\"","message":"Failed to fetch from API endpoint \"api\"","stack":"<pre><span class=\"stack internal\">at createError (/F:/nuxt3-starter/node_modules/nitropack/node_modules/h3/dist/index.mjs:48:15)</span>\n<span class=\"stack\">at /F:/nuxt3-starter/.nuxt/dev/index.mjs:517:11</span>\n<span class=\"stack internal\">at processTicksAndRejections (node:internal/process/task_queues:96:5)</span>\n<span class=\"stack internal\">at async Object.handler (/F:/nuxt3-starter/node_modules/nitropack/node_modules/h3/dist/index.mjs:681:19)</span>\n<span class=\"stack internal\">at async Server.toNodeHandle (/F:/nuxt3-starter/node_modules/nitropack/node_modules/h3/dist/index.mjs:745:7)</span></pre>","data":"422 Unprocessable Content (http://127.0.0.1:8000/api/auth/login)"}

    i cant access the validator error, also i put the $api request in a try catch, meaning it would failed and i cant access data.

    anyway you would suggest to fix the problem? :)

    opened by nhnkl159 4
Releases(v0.6.4)
Owner
Johann Schopplich
Web designer/developer. Pharmacist prior to that.
Johann Schopplich
Easily connect your Nuxt 3 application with LogSnag 📰

Nuxt LogSnag ?? LogSnag integration for Nuxt 3 ✨ Release Notes Features Nuxt 3 ready Easy integration Handy composables TypeScript support Setup Insta

Conner 13 Apr 28, 2022
A Nuxt.js module that injects a server route to serve the GraphQL Playground

@pin-pon/nuxt-graphql-playground A Nuxt.js module that injects a server route to serve the GraphQL Playground Setup Add @pin-pon/nuxt-graphql-playgrou

Pin-Pon 3 Sep 22, 2022
Http-proxy middleware for Nuxt 3.

nuxt-proxy Http-proxy middleware for Nuxt 3. Installation npm install nuxt-proxy Usage export default defineNuxtConfig({ modules: ['nuxt-proxy'],

Robert Soriano 49 Dec 30, 2022
Nuxt 3 module for Kirby's Query Language API

nuxt-kql Kirby KQL module for Nuxt 3. This module provides a useKql composable, which under the hood uses useFetch. Thus, KQL query fetching in your N

Johann Schopplich 25 Dec 15, 2022
Nuxt.js module to use Unleash toggle feature services

nuxt-unleash Nuxt.js module to use Unleash toggle feature services ?? Release Notes Features Use $unleash to access and handle your Unleash feature fl

Juanjo Conejero 15 Dec 3, 2022
🔎 Algolia module for Nuxt

@nuxtjs/algolia Algolia module for Nuxt ✨ Release Notes ?? Read the documentation Features Nuxt 3 ready Easy integration with Algolia Handy composable

Nuxt Community 128 Jan 7, 2023
Nuxt 3 module for Web3.js

nuxt-web3.js Nuxt 3 module for Web3.js. Installation npm install nuxt-web3.js Usage export default defineNuxtConfig({ modules: ['nuxt-web3.js'], })

Robert Soriano 8 Dec 16, 2022
🔎 Meilisearch module for Nuxt 3

nuxt-meilisearch Meilisearch module for Nuxt Features Nuxt 3 Easy integration with MeilisearchJS lib Support for Vue Algolia Vue 3 InstantSearch compo

Alex Duval 50 Dec 26, 2022
✉️ Nuxt module for first class integration with popular newsletter providers

nuxt-newsletter Newsletter module for Nuxt 3 ✨ Release Notes ?? Read the documentation Features Nuxt 3 ready Easy integration with Mailchimp, Revue, B

Jakub Andrzejewski 39 Jan 5, 2023
🔎 Algolia module for Nuxt

@nuxtjs/algolia Algolia module for Nuxt ✨ Release Notes ?? Read the documentation Features Nuxt 3 ready Easy integration with Algolia Handy composable

Nuxt Community 91 Jul 28, 2022
Nuxt-Module, that provides a system to set shopware cache-tags for later use in e.g. a full-page cache

nuxt-shopware-caching Nuxt-Module, that provides a system to set shopware cache-tags for later use in e.g. a full-page cache. This module is meant to

Mothership GmbH 5 Nov 8, 2022
The first truly composable CSS animation library. Built for Vue, React, SCSS, and CSS, AnimXYZ will bring your website to life.

AnimXYZ animxyz.com AnimXYZ helps you create, customize, and compose animations for your website. Powered by CSS variables to allow a nearly limitless

Ingram Projects 2.1k Jan 2, 2023
Easily remove all refs from an object using the `deepUnref`-composable.

Vue - Deep Unrefs Similar to unref(), easily remove all refs recursively from an object using the deepUnref-composable. ?? Get Started Luckily, it's i

Open Web 4 May 19, 2022
Easily remove all refs from an object using the `deepUnref`-composable.

Vue - Deep Unrefs Similar to unref(), easily remove all refs recursively from an object using the deepUnref-composable. ?? Get Started Luckily, it's i

Open Web Foundation 4 May 19, 2022
Easily connect your Nuxt3 application to your directus server. 🐰

nuxt-directus Directus Module for Nuxt 3 ✨ Release Notes ?? Read the documentation Features Nuxt3 ready Handle authentication RESTful methods TypeScri

Conner 109 Dec 28, 2022
⚡️ Minimal GraphQL Client + Code Generation for Nuxt

nuxt-graphql-client ⚡️ Minimal GraphQL Client + Code Generation for Nuxt ⚡️ Minimal GraphQL Client + Code Generation for Nuxt Features Zero Configurat

Dizzy 245 Dec 27, 2022
Easy generation of OpenGraph & Twitter meta-tags in Nuxt 3 📋

nuxt-social-tags Easy generation of OpenGraph & Twitter meta-tags in Nuxt 3 ✨ Release Notes ?? Read the documentation Features Nuxt3 ready Composables

Conner 19 Dec 17, 2022
Nuxt 3 starter with Algolia, Storyblok, and Indexer

Nuxt 3 with Storyblok CMS and Algolia Search (incl. automatic indexing) This is a demo repository for an article in Dev.to. We recommend to look at th

Jakub Andrzejewski 5 May 24, 2022