Security News
Research
Data Theft Repackaged: A Case Study in Malicious Wrapper Packages on npm
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
nuxt-api-party
Advanced tools
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.
useFetch
# pnpm
pnpm add -D nuxt-api-party
# npm
npm i -D nuxt-api-party
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.
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:
$jsonPlaceholder
– Returns the response data, similar to $fetch
useJsonPlaceholderData
– Returns multiple values similar to useFetch
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>
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
}
}
}
}
})
Option | Type | Description |
---|---|---|
|
|
API name used for composables For example, if you set it to Default value: |
|
|
API base URL For example, if you set it to Default value: |
|
|
Optional API token for bearer authentication You can set a custom header with the Default value: |
|
|
Custom query parameters sent with every request to the API Default value: |
|
|
Custom headers sent with every request to the API Add authorization headers if you want to use a custom authorization method. Default value: Example:
|
|
|
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:
|
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 toparty
.
$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:
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>
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)
}
}
corepack enable
pnpm install
pnpm run dev:prepare
pnpm run dev
MIT License © 2022-2023 Johann Schopplich
FAQs
Securely connect to any API with a server proxy and generated composables
The npm package nuxt-api-party receives a total of 1,197 weekly downloads. As such, nuxt-api-party popularity was classified as popular.
We found that nuxt-api-party demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
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.
Security News
Research
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Research
Security News
Attackers used a malicious npm package typosquatting a popular ESLint plugin to steal sensitive data, execute commands, and exploit developer systems.
Security News
The Ultralytics' PyPI Package was compromised four times in one weekend through GitHub Actions cache poisoning and failure to rotate previously compromised API tokens.