Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

nuxt-api-party

Package Overview
Dependencies
Maintainers
1
Versions
97
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

nuxt-api-party

Nuxt 3 module to securely connect with any API

  • 0.9.2
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
1.7K
decreased by-15.3%
Maintainers
1
Weekly downloads
 
Created
Source

Nuxt API Party module

nuxt-api-party

npm version

This module enables you to securely fetch data from any API by proxying the request in a Nuxt server route. Composable names are dynamic – given json-placeholder set as the module option name in your Nuxt config, the composables $jsonPlaceholder and useJsonPlaceholderData will be available globally.

Features

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 behavior 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'
  }
})

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

Singular API Endpoint

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

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>

Multiple API Endpoints

You may want to connect multiple APIs to your Nuxt application. Utilize the endpoints module option for this use-case, expecting a record of API endpoint configurations with the following type:

type ApiPartyEndpoints = Record<
  string,
  {
    url: string
    token?: string
    headers?: Record<string, string>
  }
>

ℹ️ You can keep the default endpoint as well.

The key of each item will intrinsically be used as the API name. A custom url, as well as optionally token and headers can be set in the endpoint details configuration:

export default defineNuxtConfig({
  apiParty: {
    endpoints: {
      'json-placeholder': {
        url: process.env.JSON_PLACEHOLDER_API_BASE_URL,
        token: process.env.JSON_PLACEHOLDER_API_TOKEN
      },
      'cms': {
        url: process.env.CMS_API_BASE_URL,
        headers: {
          Authorization: process.env.CMS_API_AUTH_HEADER
        }
      }
    }
  }
})

Module Options

OptionTypeDescription

name

string | undefined

API name used for composables

For example, if you set it to foo, the composables will be called $foo and useFooData.

Default value: undefined

url

string | undefined

API base URL

For example, if you set it to foo, the composables will be called $foo and useFooData.

Default value: process.env.API_PARTY_BASE_URL

token

string | undefined

Optional API token for bearer authentication

You can set a custom header with the headers module option instead.

Default value: process.env.API_PARTY_TOKEN

query

Record<string, QueryValue | QueryValue[]> | undefined

Custom query parameters sent with every request to the API

Default value: undefined

headers

Record<string, string> | undefined

Custom headers sent with every request to the API

Add authorization headers if you want to use a custom authorization method.

Default value: undefined

Example:

const username = 'foo'
const password = 'bar'

export default defineNuxtConfig({
  apiParty: {
    headers: {
      'Custom-Api-Header': 'foo',
      'Authorization': `Basic ${Buffer.from(`${username}:${password}`).toString('base64')}`
    }
  }
})

endpoints

type ApiPartyEndpoints = Record<
  string,
  {
    url: string
    token?: string
    query?: QueryObject
    headers?: Record<string, string>
  }
> | undefined

Multiple API endpoints

This will create multiple API composables for the given endpoint configurations. You can keep the default endpoint as well.

Default value: {}

Example:

export default defineNuxtConfig({
  apiParty: {
    endpoints: {
      'json-placeholder': {
        url: process.env.JSON_PLACEHOLDER_API_BASE_URL,
        token: process.env.JSON_PLACEHOLDER_API_TOKEN
      },
      'cms': {
        url: process.env.CMS_API_BASE_URL,
        headers: {
          Authorization: process.env.CMS_API_AUTH_HEADER
        }
      }
    }
  }
})

Composables

Customize your API's composable names with the name in your Nuxt config module option. Given it is set to json-placeholder, the composables $jsonPlaceholder and useJsonPlaceholderData will be available globally.

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

$party (Respectively Camel-Cased API Name)

Returns the raw response of the API endpoint. Intended for actions inside methods, e. g. when sending form data to the API when clicking a submit button.

Responses can be cached between function calls for the same path based on a calculated hash by setting cache to true.

Type Declarations

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

type ApiFetchOptions = Omit<NitroFetchOptions<string>, 'body'> & {
  body?: string | Record<string, any> | FormData | null
  /**
   * Skip the Nuxt server proxy and fetch directly from the API.
   * Requires `allowClient` to be enabled in the module options as well.
   * @default false
   */
  client?: boolean
  /**
   * Cache the response for the same request
   * @default false
   */
  cache?: boolean
}

Example

<script setup lang="ts">
const data = await $party(
  'posts',
  {
    method: 'POST',
    body: {
      foo: 'bar'
    },
    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 (Respectively Pascal-Cased API Name)

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.

Responses are cached between function calls for the same path based on a calculated hash. You can disable this behavior by setting cache to false.

The composable supports every useAsyncData option.

Type Declarations

function usePartyData<T = any>(
  path: MaybeComputedRef<string>,
  opts?: UseApiDataOptions<T>,
): AsyncData<T, FetchError>

type UseApiDataOptions<T> = AsyncDataOptions<T> & Pick<
  ComputedOptions<NitroFetchOptions<string>>,
  | 'onRequest'
  | 'onRequestError'
  | 'onResponse'
  | 'onResponseError'
  | 'query'
  | 'headers'
  | 'method'
> & {
  body?: string | Record<string, any> | FormData | null
  /**
   * Skip the Nuxt server proxy and fetch directly from the API.
   * Requires `allowClient` to be enabled in the module options as well.
   * @default false
   */
  client?: boolean
  /**
   * Cache the response for the same request
   * @default true
   */
  cache?: boolean
}

Basic 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>

Example including all parameters

<script setup lang="ts">
const postId = ref(1)
const { data, pending, refresh, error } = await usePartyData('comments', {
  // Whether to resolve the async function after loading the route, instead of blocking client-side navigation (defaults to `false`)
  lazy: false,
  // A factory function to set the default value of the data, before the async function resolves - particularly useful with the `lazy: true` option
  default: () => ({
    foo: 'bar'
  }),
  // Whether to fetch the data on the server (defaults to `true`)
  server: true,
  // A function that can be used to alter handler function result after resolving
  transform: res => res,
  // When set to `false`, will prevent the request from firing immediately. (defaults to `true`)
  immediate: true,
  // Watch reactive sources to auto-refresh
  watch: [],
  // Custom query parameters to be added to the request, can be reactive
  query: computed(() => ({
    postId: postId.value
  })),
  // Custom headers to be sent with the request
  headers: {
    'X-Foo': 'bar'
  }
})
</script>

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

FAQ

How Can I Inspect the Error Thrown by My API?

Although the idea of this module is to mask your real API by creating a Nuxt server proxy, nuxt-api-party will forward error responses – including statusCode, statusMessage as well as the API response body as data – to the client if your API fails to deliver.

Example usage with useJsonPlaceholderData()

const { data, error } = await useJsonPlaceholderData('not-found')
watchEffect(() => {
  console.error('statusCode:', error.value.statusCode)
  console.error('statusMessage:', error.value.statusMessage)
  console.error('data:', error.value.data)
})

Example usage with $jsonPlaceholder()

function onSubmit() {
  try {
    const response = await $jsonPlaceholder('not-found', {
      method: 'POST',
      body: form.value
    })
  }
  catch (e) {
    console.error('statusCode:', e.statusCode)
    console.error('statusMessage:', e.statusMessage)
    console.error('data:', e.data)
  }
}

💻 Development

  1. Clone this repository
  2. Enable Corepack using corepack enable
  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-2023 Johann Schopplich

Keywords

FAQs

Package last updated on 22 Feb 2023

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc