Giter Club home page Giter Club logo

nuxt-api-party's Introduction

nuxt-api-party

Nuxt API Party

npm version

Nuxt module to securely connect to any API.

Features

Setup

npx nuxi@latest module add api-party

Basic Usage

Add the Nuxt API Party to your Nuxt config and prepare your first API connection by setting an endpoint object with the following properties for the apiParty module option:

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

  apiParty: {
    endpoints: {
      jsonPlaceholder: {
        url: process.env.JSON_PLACEHOLDER_API_BASE_URL!,
        // Global headers sent with each request
        headers: {
          Authorization: `Bearer ${process.env.JSON_PLACEHOLDER_API_TOKEN}`
        }
      }
    }
  }
})

If you were to call your API jsonPlaceholder, the generated composables are:

Use these composables in your templates or components:

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

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

Tip

You can connect as many APIs as you want, just add them to the endpoints object.

πŸ’» 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-PRESENT Johann Schopplich

nuxt-api-party's People

Contributors

brawaru avatar danielroe avatar johannschopplich avatar killjoy1221 avatar mbaertschi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

nuxt-api-party's Issues

Pass-through client request headers / set X-Forwarded for

Describe the feature

There should be an option similiar to how it's done for the response headers in #44 to pass client request headers to the server.

Use case:

  • User-Agent / Client IP (X-FORWARED-FOR header)

Right now our main api receives User-Agent: node and the ip-address of the node server.

Right now to achieve this, we need to create a custom route and proxy them ourselves. We cannot set client: true ,because this would expose an Authorization header that we set.

Additional information

  • Would you be willing to help implement this feature?
  • Can you think of other implementations of this feature?

Final checks

Allow headers to pass-through to the response on the client

Describe the feature

When using API-Party and making a request to a backend, default functionality should be for headers to pass-through to the client, and maybe have an ability filter them.

On the below images, we see one of the request responses using the native Fetch function sending a request directly to the endpoint, and the other using API Party.

I checked if any feature related to this issue existed in API Party but didn't find anything.

image
image

If this is a non-feature, let me know how can I solve this in any other way.

Additional information

  • Would you be willing to help implement this feature?
  • Can you think of other implementations of this feature?

Final checks

`useApiData` is not defined on server routes

Environment



Reproduction

https://stackblitz.com/edit/github-9fp4zu?file=app.vue

Describe the bug

im trying to use what the api party module to call an outside api from the server side, but it doesnt seem to work, i tried to check the docs, but couldnt find anything related to this issue, on another note im using the trpc module and i would like to keep my logic in the server files, not sure if there's a solution to this issue.

Additional context

No response

Logs

[nuxt] [request error] [unhandled] [500] useJsonPlaceholderData is not defined                    20:57:19
  at eval (file://./.nuxt/dev/index.mjs:731:27)  
  at eval (file://./node_modules/h3/dist/index.mjs:1290:14)  
  at Object.eval [as handler] (file://./node_modules/h3/dist/index.mjs:1533:12)  
  at Object.eval [as handler] (file://./node_modules/h3/dist/index.mjs:1348:31)  
  at async toNodeHandle (file://./node_modules/h3/dist/index.mjs:1423:7)  
  at async ufetch (file://./node_modules/unenv/runtime/fetch/index.mjs:28:17)  
  at async $fetchRaw2 (file://./node_modules/ofetch/dist/shared/ofetch.502a4799.mjs:197:24)
[nitro] [dev] [unhandledRejection] [FetchError:  (500  (/api/test))]

TypeScript error when using `transform` option

Environment

https://stackblitz.com/~/github.com/brawaru/nuxt-api-party-test (vanilla Stackblitz doesn't have Volar)

Reproduction

  1. Have API typed using OpenAPI
  2. Use useEndpointData composable, but pass transform method in it to modify the response (e.g. select a subset of response data)

Describe the bug

TypeScript will not accept your transform method because its return type doesn't match the original response type, neither the data will have a correct type. This doesn't match the reality though, as evident by result on the page after it's compiled unchecked by Vite.

Additional context

N/A

Logs

N/A

Security concern

Hello πŸ‘‹

I run a security community that finds and fixes vulnerabilities in OSS. A researcher (@OhB00) has found a potential issue, which I would be eager to share with you.

Could you add a SECURITY.md file with an e-mail address for me to send further details to? GitHub recommends a security policy to ensure issues are responsibly disclosed, and it would help direct researchers in the future.

Looking forward to hearing from you πŸ‘

(cc @huntr-helper)

Inconsistent openapi-typescript import

Environment


  • Operating System: Linux
  • Node Version: v18.16.0
  • Nuxt Version: 3.6.5
  • Nitro Version: 2.5.2
  • Package Manager: [email protected]
  • Builder: vite
  • User Config: modules, apiParty, typescript
  • Runtime Modules: [email protected]
  • Build Modules: -

Reproduction

Reproduction can be done with the playground being run separate from the rest of the repo.

cp -r playground ../api-playground
cd ../api-playground
echo 'shamefully-hoist=true' > .npmrc
pnpm add -D nuxt nuxt-api-party openapi-typescript
pnpm nuxi prepare

Describe the bug

Whether openapi-typescript is imported as a module or function seems to depend on whether the package is installed in node_modules. When in node_modules, it behaves as expected, being imported as a module. Otherwise, it imports the function. I'm not sure whether this is an issue with node or typescript.

I suggest the following change to openapi.ts.

diff --git a/src/openapi.ts b/src/openapi.ts
index 2527990..cc84fd5 100644
--- a/src/openapi.ts
+++ b/src/openapi.ts
@@ -3,6 +3,15 @@ import { useNuxt } from '@nuxt/kit'
 import type { OpenAPI3, OpenAPITSOptions } from 'openapi-typescript'
 import type { Endpoint } from './module'

+function importOpenapiTypescript() {
+  return import('openapi-typescript').then((openapiTS) => {
+    // The import is somehow different during dev and prod
+    if (typeof openapiTS === 'function')
+      return openapiTS
+    return openapiTS.default
+  })
+}
+
 export async function generateTypes(
   endpoints: Record<string, Endpoint>,
   globalOpenAPIOptions: OpenAPITSOptions,
@@ -15,7 +24,7 @@ export async function generateTypes(
       throw new Error('Caught process.exit()')
   })

-  const openapiTS = await import('openapi-typescript')
+  const openapiTS = await importOpenapiTypescript()
   const schemas = await Promise.all(
     Object.keys(endpoints).map(async (id) => {
       let types = ''
@@ -25,7 +34,6 @@ export async function generateTypes(
       runningCount++

       try {
-        // @ts-expect-error: ESM import type mismatch
         types = await openapiTS(schema, {
           commentHeader: '',
           ...globalOpenAPIOptions,

Additional context

No logs were created to indicate an error, just the types not being generated. When I edited the javascript to add a console.error() inside the catch block surrounding openapiTS(), I got the error openapiTS is not a function.

Logs

ERROR  openapiTS is not a function                                                                                                                                                                                                          5:02:09 PM

  at /home/username/api-playground/node_modules/.pnpm/[email protected]/node_modules/nuxt-api-party/dist/module.mjs:20:23
  at async Promise.all (index 0)

OpenAPI schemas with a default value aren't marked as optional

Environment

❯ npx nuxi info
Working directory: /home/projects/nuxt-starter-8hsfcz
Nuxt project info:

------------------------------
- Operating System: Linux
- Node Version:     v18.18.0
- Nuxt Version:     3.11.2
- CLI Version:      3.11.1
- Nitro Version:    2.9.6
- Package Manager:  [email protected]
- Builder:          -
- User Config:      modules, watch, apiParty, devtools
- Runtime Modules:  [email protected]
- Build Modules:    -
------------------------------

Reproduction

https://stackblitz.com/edit/nuxt-starter-qqitc3?file=nuxt.config.ts

Describe the bug

Components with a default value and aren't included in the required key aren't marked as optional in the resulting typescript declarations.

Additional context

Input schema:

components:
  schemas:
    UserRegistration:
      type: object
      properties:
        name:
          type: string
        age:
          type: number
        subscribe:
          type: boolean
          default: true
      required: [ name ]

Output .d.ts

export interface components {
  schemas: {
    UserRegistration: {
      name: string;
      age?: number;
      /** @default true */
      subscribe: boolean;
    }
  }
}

Logs

No response

UI Freezing when uploading data through Nuxt API Party

Environment

Operating System: Darwin

Reproduction

Not applicable.

Describe the bug

 const {
        data: { value: task },
        pending,
        error,
        refresh,
      } = await useConfide("vi/api/dataset/upload", {
        method: "POST",
        body: formData,
      });

When I'm using the above function which is a wrapper and abstraction on top of the NuxtApiParty, the UI glitches and takes a bit of time to upload, in some cases crashes the browser.

CleanShot.2023-09-09.at.12.54.27.mp4

On the other hand, I have done another implementation with Axios and a proxy URL with routeRules, and that works completely fine, no glitches, nothing.

CleanShot.2023-09-09.at.12.57.10.mp4

Additional context

No response

Logs

No response

Query change in route not detected properly

I was trying to implement pagination with hook usePartyData

On the page I have this code:

const route = useRoute();
const { $apiUrl } = useNuxtApp();

const {
  data,
  error,
  pending,
} = await usePartyData($apiUrl("chapter"), {
  query: computed(() => ({
    page: route.query?.page || 1,
  })),
});

For pagination links I'm having separate custom pagination component which automatically generates pagination links from 1 to total pages using NuxtLink like below:

<NuxtLink
  class="btn"
  :class="{ 'btn-active': item.selected }"
  :to="{ query: { ...$route.query, page: item.page } }"
>
          {{ item.page }}
</NuxtLink>

The pagination works perfectly fine and changes query page value in URL when I click on the link without any problem, the problem is after initial load, with data for page 1, I then click to page 2 which loads in the new data. But when I click back on page 1 the data rendered is still for page 2.

I have tested adding route returned from useRoute() to watch and tried with reactive variable and watching the variable and on change of route query value, I made it to change variable value and added this reactive variable to watch instead, but didn't work. I added both route and a reactive variable holding page number to watch and still didn't work.

I switched back to useFetch and tested, without any of these extra code, just with the initial code it works fine.

Clear cache on error in response

Describe the feature

Hello great work on this project. It's a super useful module for us that eliminates a ton of code - really appreicate the work!

I was wondering if a feature to disable or remove the cache for a reponse if the response returns an error would be possible?

My use case is:

i have blog/[slug]. In my nuxt page i call GET blog/{id} - if my backend returns a 404 i redirect to error page. Now if the user again tries to access the same route blog/[slug] and the backend still returns 404 my fetch in the frontend will no longer return an error object because the previous response is still in the cache and I can't check if I should redirect the user to my error page.

I could disable caching for this route but I don't necessarily want to disable caching if the user navigates between different blog/[slug] routes and the response was a 200 the first time.

Does this makes sense? :)

Additional information

  • Would you be willing to help implement this feature?
  • Can you think of other implementations of this feature?

Final checks

Need to integrate with Nuxt simple sitemap module

Describe the feature

Hi,

Currently i want to create a sitemap.xml with dynamic url that should fetch the data from every dynamic pages.

The issue is jsonPlaceholder is not defined, i already config the suit-party on nuxt.config

Additional information

  • Would you be willing to help implement this feature?
  • Can you think of other implementations of this feature?

Final checks

useApiData: custom key is always `true`

Environment

N/a

Reproduction

const nuxt = useNuxtApp()
console.log(Object.keys(nuxt.payload.data)) // []
await useApiData("...", {
  key: "somekey"
});
console.log(Object.keys(nuxt.payload.data)) // ["$apiPartytrue"]

Describe the bug

Provide a custom key to useApiData and compare nuxt.payload.data before and after. No matter what key you use, the key will be true.

This line probably got missed when changing the cache key from cache -> key.

: () => CACHE_KEY_PREFIX + toValue(cache),

It was also missed in $api

: CACHE_KEY_PREFIX + cache

Additional context

No response

Logs

No response

Enable module to work with Nitro `routeRules`

Describe the feature

Would it be possible to extend functionality so that /api/__api_party/${endpointId} routes can be cached in nitro by routeRules that we can define in nuxt.config.ts?

I don't have much knowledge about the inner workings of Nuxt and Nitro so maybe this is not possible to modules but it seems like this would be a great benefit.

Currently in my project I have a bunch for endpoints delivering some SEO content that I would like to cache for an extended period of time. Currently it doesn't seem possible to use the api-party composables fetch this data and have it cached by Nitro. This means I have to manually create endpoints in my server/api folder and use a mix of useFetch for cacheable endpoints and api-party composables for non-cachable endpoints which leads to a very confusing DX.

Additional information

  • Would you be willing to help implement this feature?
  • Can you think of other implementations of this feature?

Final checks

Global headers not configured properly in `nuxt.config.ts`

Environment



Reproduction

https://codesandbox.io/p/sandbox/admiring-kilby-x69gsn

This repository doesn't seem to be able to view network information properly in CodeSandbox, so you may need to launch it in VS Code.

To avoid additional errors, the Url in the playground provided by nuxt-api-party is used here

Describe the bug

My English is not very good, so the following is translated from translation software. I apologize if it has caused any unnecessary trouble.

I made the following configuration in nuxt.config.ts:

apiParty: {
    endpoints: {
      proxyAsync: {
        url: 'https://a8i4pp1q.beesnat.com',
        headers: {
          Authorization: 'test',
        },
      },
    },
  },

I want the request to carry a request header for authentication, but it doesn't work, all web requests to the server have headers with a value of {}.

Additional context

In my search, I found #10 issue that talks about this. I'm assuming that the issue may have something to do with the "Authorization" field.

Logs

No response

Error when fetching from `localhost`, but fine from `127.0.0.1`

Issue

nuxt-api-party is unable to fetch from localhost, but substituting it with 127.0.0.1 with the exact same setup works perfectly.

The API response is identical for both localhost and 127.0.0.1 when tested manually. Additionally, the backend logs do not show any footprints at all when localhost is used, so I believe that this is an issue with nuxt-api-party.

❌ Broken (localhost:8000)

Config

  apiParty: {
    endpoints: {
      backend: {
        url: "http://localhost:8000",
      },
    },
  },

Execution

const data = await $backend("/api/users/lloydtao/?format=json");

Error

[nitro] [dev] [unhandledRejecto 
n] FetchError: 500 Failed to fetch from API endpoint "backend" (/api/__api_party/backend)       
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async fetcher (S:\Users\Lewis\Documents\GitHub\gridlink\frontends\web\node_modules\nuxt-api-party\dist\runtime\composables\$api.mjs:22:31)
    at async Proxy.fetchUser (S:\Users\Lewis\Documents\GitHub\gridlink\frontends\web\stores\user.ts:20:20)

API

Returning as expected when called manually:

image

βœ”οΈ Working (127.0.0.1:8000)

Config

  apiParty: {
    endpoints: {
      backend: {
        url: "http://127.0.0.1:8000",
      },
    },
  },

Execution

const data = await $backend("/api/users/lloydtao/?format=json");

Output

{
  "username": "lloydtao",       
  "profile": {
    "display_name": "leighton",
...

API

Returning as expected when called manually:

image

Can't fetch data in v0.11.3

Environment

Reproduction

Here's a link to StackBlitz with a minimal reproduction

Note that the reproduction was recreated using the Getting started steps.

Describe the bug

On ver 0.11.3 I cant seem to get any data.
When viewing the ref in vue dev tools I get the following error
This screen shot was taken from my project
Screenshot 2023-05-29 163820

Additional context

Initially I was trying to fetch data using useAsyncData
Here's a snippet of the code I was trying to work with.

<script setup>
  import qs from 'qs'
  import { get } from '@vueuse/core'
  const query = computed(() =>
    qs.stringify(
      {
        populate: 'deep',
      },
      {
        encodeValuesOnly: true,
      }
    )
  )

  const { data: footerSeo, error } = await useAsyncData(
    'footer',
    () => {
      return $cms(`seo?${get(query)}`, { cache: true })
    },
    {
      watch: [query],
    }
  )

  const footerData = computed(
    () => get(footerSeo).data.attributes.seo.metaSocial
  )
</script>

I want to note that downgrading the package to v 0.10.5 fixed this issue and the above code works.

Logs

statusCode: 500                                                                                                 
data: undefined                                                                                                 
statusMessage: undefined

UseApiDataOptions: Add transform from AsyncDataOptions

We often use transform parameter from useAsyncData options in our projects. It lets you transform data before setting to the ".data" ref and I can't find any alternative solutions to implement this other than awaiting the async data and transforming it afterwards which defys the whole point of useAsyncData for me.
Can we add transform from AsyncDataOptions to UseApiDataOptions and pass it to useAsyncData or is there some non-obvious reason you left it out?

Module configuration questions

firstly thank you guys for your amazing work and simple/clean documentation.

I don't know if my approach of spelling all my questions in one form is good or not, but I will do it so please bear with me :).

  • I just notice that the header in the config file is not been passed in the call it shows an empty header I need to pass in the call for it to show in the call, this was my setup in the config for the endpoint for testing
authAPI: {
       headers: {
         Authorization:"bearer 1234567890",
       },
       url: "http://localhost:9051/api/authenticate",
     },
  • and second, about cache = true by default this one I think needs to be in config because it is not useful in most cases because it makes one call and needs to refresh to make another call each time

  • and the third, was about global interceptors if there is a way to make it it will be awesome to see

Global headers can be overridden

Describe the feature

Example ?

export const useApiFetch = <P extends GETPlainPaths<paths>>(
  path: MaybeRefOrGetter<P>,
  opts?: Omit<UseOpenApiDataOptions<paths[`/${P}`], IgnoreCase<keyof paths[`/${P}`] & "get">>, "method"> | undefined,
): AsyncData<P | undefined, FetchError<any>> => {
  return useApiData(path, <any>{
    ...opts,
    onRequest(context): Promise<void> | void {
      context.options.headers = {
        ...context.options.headers,
        'x-api-key': '123', //TODO: get api key from authjs
      }
    }
  })
}

Additional information

  • Would you be willing to help implement this feature?
  • Can you think of other implementations of this feature?

Final checks

Support `body` as reactive variable

Environment

nuxt3

Reproduction

no

Describe the bug

When I do not use .value with selId, he will be sent as a ref object. When I use .value, the selId change cannot change the result of the request. He will always issue the request with the initial value.

const { data:moneyData, refresh } = await useApi3FetchData("ack_pay/web/pay",{
                method:"POST",
                body:{
                    qmSig: useCookieToken().value,
                    cardId: selId.value,
                    buyType: selTab.value,
                    source: 2,
                    versionNumber: 0
                },
                watch:[selId, selTab],
                cache:false,
                onRequest(context) {
                    console.log(context);
                },
            });

When I use native useFetch it will work properly, whether this is a BUG or not

const { data:moneyData, refresh } = await useFetch("https://xxx.xxx.com/ack_pay/web/pay",{
                method:"POST",
                body:{
                    qmSig: useCookieToken().value,
                    cardId: selId,
                    buyType: selTab,
                    source: 2,
                    versionNumber: 0
                },
            });

Additional context

No response

Logs

No response

Support for passing API error

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? :)

Add a retry option to `UseApiDataOptions`

Describe the feature

Im currently using something like this in my project to retry a failed fetch.

const fetchData = async () => {
    let tries = 0
    const maxTries = 3

    const { refresh, error, data } = await useApiData(
        "path/to/api",
    );
    while (error.value && tries < maxTries) {
        tries++;
        await refresh();
    }
    if (error.value) {
        //handle error..
    }
    return data.value
}

My suggstion would be to add an option to UseApiDataOptions to enable retries if a fetch fails.

await useApiData(
    "path/to/api",
    {
        retries: 3
    }
)

Thanks !

Additional information

  • Would you be willing to help implement this feature?
  • Can you think of other implementations of this feature?

Final checks

Client and server error data is inconsistent

Environment

N/a

Reproduction

<script>
// serverError.data = { url: "/api/__api_party/api", statusCode: 400, statusMessage: "Bad Request", message: "Bad Request", stack: "<pre>...",  data: { message: "This is an error" }}
const { error: serverError } = useApiData("someerror")
// clientError.data = { message: "This is an error" }
const { error: clientError } = useApiData("someerror", {
  client: true
})
</script>

Describe the bug

When switching between client and server on the same endpoint, the error returned is different. When using a client endpoint, as expected, the error data is returned from the backend as is. Though when using a server endpoint, it returns the error data wrapped in another object. This can be confusing if you're not expecting it.

One option to solve this would be to inline the error manually inside the composable error handler.

catch (error) {
  if (!client && error instanceof FetchError && error.response) {
    const { response } = error
    response._data = response._data?.data
  }
  throw error
}

This would be a breaking change.

Additional context

I discovered this while tinkering with #38. As it may involve a breaking change, I figure I should open an issue for it first.

Logs

No response

Multiple form data files not sent

I have been using "Nuxt Api Party" in my project for a while now, but I have encountered a problem with sending multiple images.

The problem occurs whenever I try to send multiple images. The "Nuxt Api Party" form data serialises my Formdata and only adds the first image in my request and disregards the rest as shown in the screenshot below:

image

even though I have added two images (below is the console log for Formdata values):
image

I have been stuck on this problem for awhile now, is there a way to send multiple images or files ?
Any help is much appreciated, thanks.

Originally posted by @NebilSahin in #59

`refresh()` is not forcing API call and the cached result is returned

Environment

Working directory: /home/anwr/toys/darts_arena/frontend                                                              4:10:00 PM
Nuxt project info:                                                                                                   4:10:00 PM
------------------------------
- Operating System: Linux
- Node Version:     v18.16.0
- Nuxt Version:     3.11.1
- CLI Version:      3.11.1
- Nitro Version:    2.9.4
- Package Manager:  [email protected]
- Builder:          -
- User Config:      ssr, runtimeConfig, devtools, css, modules, vue, imports, apiParty
- Runtime Modules:  @nuxtjs/[email protected], @vueuse/[email protected], @pinia/[email protected], [email protected], [email protected]
- Build Modules:    -
------------------------------

Reproduction

<template>
    <main class="mx-auto max-w-xl">
      <div v-if="pending" class="w-full py-4 flex justify-center items-center">
        <span class="px-2">Loading Posts</span>
        <span class="loading loading-spin"></span>
      </div>
      <button @click="refresh">Refresh</button>
      <PostList :posts="data" />
    </main>
  </div>
</template>

<script setup>
definePageMeta({
  layout: "main",
});
const { data, pending, refresh } = await useApiData("posts");
</script>

Describe the bug

When the Refresh button is clicked, the API is not called and the cached result is returned.
Is that the expected behavior? I can't find any reference for that in the docs.

A workaround would be to use a custom cache key and change it if I wanted to refresh the content. otherwise, I have to set the cache to false

Additional context

No response

Logs

No response

`getRequestHeader` is not defined

Environment

                                                                                                                                                                                            9:22:07 AM

RootDir: /Users/mike/dev/demo/sbr2-datastore 9:22:07 AM
Nuxt project info: (copied to clipboard) 9:22:07 AM



Reproduction

Describe the bug

If cookies is enabled, nuxt-api-module server module tries to extract the cookie request header with getRequestHeader from the h3 module (see here).

At runtime the getRequestHeader function is not available as it is not imported from h3. Please import it so that this feature works as expected :-)

Additional context

No response

Logs

No response

Generate types from Swagger/OpenAPI schemas

Describe the feature

A huge benefit of writing your backend endpoints using nuxt is the type inference in useFetch and $fetch. Not only do you get types for the path, but also the request and response data. You don't get that benefit when using API Party. Without types, it's not much of a party.

Some services provide a json file describing the API, including paths and component models. Some frameworks even provide the functionality by default.

Configuration

I suggest implementing a config that can load a spec from a url, file, or object.

Here's an example.

// nuxt.config.ts
export default defineNuxtConfig({
  modules: ['nuxt-api-party'],
  apiParty: {
    endpoints: {
      httpbin: {
        url: "https://httpbin.org",
        // URL to the API spec. Could also be a file path or object containing the spec.
        spec: "https://httpbin.org/spec.json"
      }
    }
  }
})

Implementation

For implementation, I would suggest using openapi-typescript as an optional peer dependency to generate the types. Some types can probably be borrowed from the openapi-fetch package to create the useXXX() types.

Note though that the latest version only supports openapi, and not swagger, which httpbin uses. Developers would have to install v5 instead of v6.

Additional information

  • Would you be willing to help implement this feature?
  • Can you think of other implementations of this feature?

Final checks

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!

Multiple Set-Cookie gets merged into one

Environment



Reproduction

Not sure exactly how to provide a server reproduction but the problematic code is right here: https://github.com/johannschopplich/nuxt-api-party/blob/v0.21.0/src/runtime/server/handler.ts#L75

The reproduction on this line would be the following

const headers = new Headers()
headers.append('Set-Cookie', 'a=a')
headers.append('Set-Cookie', 'b=b')
headers.append('Content-Type', 'application/json')

headers.getSetCookie()
['a=a', 'b=b']

Object.fromEntries(headers.entries())
{content-type: 'application/json', set-cookie: 'b=b'}

Describe the bug

Multiple response headers under the same name such as "Set-Cookie" gets merged into one and thus client never receiving fully the whole cookie from server.

Additional context

Similar case from unjs/h3 repo: unjs/h3#384

Logs

No response

SSE implemention

Describe the feature

Hello Johann,

thank you again for your great work.

I was wondering how to implement SSE requests using the package.
if you have any suggestions on how to work this out, I will appreciate it.

Additional information

  • Would you be willing to help implement this feature?
  • Can you think of other implementations of this feature?

Final checks

The refresh() is not working properly

Environment



Reproduction

https://codesandbox.io/p/sandbox/happy-rubin-r396mz

Describe the bug

When I use refresh(), the data doesn't get updated, and even the network request doesn't happen. So I used Nuxt3's native useFetch(), which can send network requests even though it doesn't fetch the data properly (because no proxy is configured).

Is this nuxt-api-party's fault? Or does it need to be written differently to achieve this effect?

I'm sorry if this problem bothers you.

Additional context

No response

Logs

No response

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

Allow change "__api_party" endpoint

Describe the feature

Allow change "__api_party" endpoint string

Additional information

  • Would you be willing to help implement this feature?
  • Can you think of other implementations of this feature?

Final checks

Support for multiple APIs

Would be nice to have support for multiple apis - with multiple composables generated: useApi1Data, useApi2Data

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

POST request with caching enabled and a body containing different data is treated as same request

Would it be possible to cache requests based on the content of the body of the request and not only the path?

E.g. right now with caching enabled

If I make this request

const data = await $party(
  'some-url',
  {
    method: 'POST',
    body: {
      foo: 'bar'
    },
)

and afterwards the same request but with a different body

const data = await $party(
  'some-url',
  {
    method: 'POST',
    body: {
      bar: 'foo'
    },
)

the request won't return the correct data as it will hit the cache.

Payload is not being updated after `refresh()`

Environment



Reproduction

  1. Make a normal call to any Nuxi Api Party autogenerated functions with cache: false
  2. Call refresh()
  3. watchEffect the data payload and assign it to any pinia state

Describe the bug

The data property should return the newly updated payload, but returns the old initial payload from the request.
The request is successful and I can see the data being sent over by the backend/proxy, but the data is not propagated to the data property.

The watchEffect methods throws successfully when refresh executes, but the data returned is the old data/payload (as there's missing fields and information from the payload`

Additional context

No response

Logs

No response

Error in POST reques with body

Environment


  • Operating System: Linux
  • Node Version: v20.5.1
  • Nuxt Version: 3.7.0
  • CLI Version: 3.8.4
  • Nitro Version: 2.6.3
  • Package Manager: [email protected]
  • Builder: -
  • User Config: -
  • Runtime Modules: -
  • Build Modules: -

Reproduction

I have some routeRules defined in my nuxt.config.ts which aprrently breaks the caching in the API party module.
If you try to render the page without routeRules then it works.
If you try to render the page with routeRules then it breaks.

https://stackblitz.com/edit/github-eequg2?file=app.vue

Describe the bug

server side POST request with body returns undefined and on client it returns an error

Additional context

No response

Logs

No response

Server handler does not forward headers to client

Environment


  • Operating System: Linux
  • Node Version: v18.16.0
  • Nuxt Version: 3.6.5
  • CLI Version: 3.7.2
  • Nitro Version: 2.5.2
  • Package Manager: [email protected]
  • Builder: -
  • User Config: extends, appConfig, modules, apiParty, runtimeConfig, experimental
  • Runtime Modules: [email protected]
  • Build Modules: -

Reproduction

N/a

Describe the bug

When using the server handler, headers are not being forwarded from the API server to the client. I'm aware that headers are not normally accessible using the $api function, but they are when using useApiData(..., { onResponse }) and via FetchError.response. Additionally, if an API sets a cookie, it will be unable to do it as the Set-Cookie header is discarded.

Additional context

Depending on how you feel, this may be a feature request instead of a bug report.

Logs

No response

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>

`FormData` no longer supported

Version: >=v0.6.5

When trying to send FormData as the request body the following error is thrown:

Error: Unknown object type "formdata"

This seems to be introduced by using body in the key hash: 38a71e0
It seems like the same issue (nuxt/framework#5661) as Nuxt faced. See ohash issue: unjs/ohash#10

As a workaround I switched to v0.6.4.

`cache: false` not working in production

Environment

Mac os
Nuxt 3.6.5

Reproduction

https://px.saga.id

Describe the bug

In the section Why Px, in CMS i hide the section via API response but when i reload to get new response, the section still exist not hide. the case same as with nuxt useFetch

Additional context

No response

Logs

No response

Get status code from `useApiData`

Describe the feature

Currently when I do this:

const { status } = await usApiData("/posts", { ... })
console.log(status.value)

I get "success" as long as no error happened, but I don't get any other values

It would be nice if we could get the status code by doing (for example): status.value.code

Additional information

  • Would you be willing to help implement this feature?
  • Can you think of other implementations of this feature?

Final checks

When `immediate` is set to `false`, `pending` is always `true`

Environment



Reproduction

const {
  data,
  pending,
} = await useApiData("/posts", {
  method: "GET",
  query: computed(() => ({ query: searchTerm.value })),
  watch: false,
  immediate: false, // <-- when this is commented out, `pending` behaves correctly
  default: () => [],
});

Describe the bug

When I set immediate option to false, the pending Ref is always true

Additional context

No response

Logs

No response

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.