https://github.com/cocreators-ee/apity
A typed fetch client for openapi-typescript for use with SvelteKit
https://github.com/cocreators-ee/apity
api fetch openapi openapi3 svelte sveltekit ts typescript
Last synced: 6 months ago
JSON representation
A typed fetch client for openapi-typescript for use with SvelteKit
- Host: GitHub
- URL: https://github.com/cocreators-ee/apity
- Owner: cocreators-ee
- License: mit
- Created: 2023-01-20T08:55:39.000Z (over 3 years ago)
- Default Branch: main
- Last Pushed: 2025-04-10T08:05:20.000Z (over 1 year ago)
- Last Synced: 2025-09-25T17:49:56.063Z (10 months ago)
- Topics: api, fetch, openapi, openapi3, svelte, sveltekit, ts, typescript
- Language: TypeScript
- Homepage:
- Size: 536 KB
- Stars: 58
- Watchers: 0
- Forks: 3
- Open Issues: 11
-
Metadata Files:
- Readme: README.md
- Contributing: .github/CONTRIBUTING.md
- Funding: .github/FUNDING.yml
- License: LICENSE
Awesome Lists containing this project
README
# 📘️ apity - Typed API client for Svelte and SvelteKit
A typed fetch client for [openapi-typescript](https://github.com/drwpow/openapi-typescript) compatible with SvelteKit's custom `fetch`
## Installation
```bash
npm install @cocreators-ee/apity
```
Or
```bash
pnpm add @cocreators-ee/apity
```
## Features
- [x] Support of JSON request and responses from [OpenAPI 3.0](https://swagger.io/specification)
- [x] Support of `{#await}` syntax in Svelte templates
- [x] Compatibility with SvelteKit's `fetch` in `load` functions
- [x] Request reloading
- [x] Configuration of default [fetch options](https://developer.mozilla.org/en-US/docs/Web/API/fetch#parameters)
On the roadmap:
- [ ] Caching of subsequent requests with the same URL and parameters
### Live demo
Apity has a [live demo](https://apity-demo.vercel.app/) with code samples.
Also you can read an introductionary [blog post](https://dev.to/fbjorn/a-typed-http-client-for-sveltekit-88b).
## Usage
### Generate typescript definition from schema
Before working with the library, you need to generate an API spec using [openapi-typescript](https://www.npmjs.com/package/openapi-typescript):
```bash
npx openapi-typescript https://petstore3.swagger.io/api/v3/openapi.json --output src/petstore.ts
🚀 https://petstore3.swagger.io/api/v3/openapi.json → file:./src/petstore.ts [870ms]
```
### Using Apity
Configure Apity instance and generate functions for making API calls:
```ts
// File: api.ts
import { Apity } from '@cocreators-ee/apity'
import type { paths } from 'src/petstore'
const apity = Apity.for()
// global configuration
apity.configure({
// Base URL to your API
baseUrl: 'https://petstore.swagger.io/v2',
// RequestInit options, e.g. default headers
init: {
// mode: 'cors'
// headers: {}
},
})
// create fetch operations
export const findPetsByStatus = apity
.path('/pet/findByStatus')
.method('get')
.create()
export const addPet = apity.path('/pet').method('post').create()
```
Each API call is represented as a request object that has the following properties:
```typescript
type ApiRequest = {
// Svelte store containing the response of the API call.
readonly resp: Writable | undefined>
// Svelte store that contains a promise for an API call.
// If you reload the request using reload() function, this store will be updated.
readonly ready: Writable>>
// Function that reloads the request with the same parameters.
reload: () => Promise>
// Promise for the API call.
// Useful for server code and places where you can't use the `ready` store.
result: Promise>
}
```
Each response is a Svelte store returning either an `undefined`, or the following object:
```ts
type SuccessfulResp = {
ok: true
// Typed object for a successful request. Built from the OpenAPI spec
data: R
// HTTP status code
status: number
}
type FailedResp = {
ok: false
data: any
// HTTP status code
status: number
}
type ApiResponse = SuccessfulResp | FailedResp
```
### Error handling
There are certain conditions under which an API request could throw an exception without
actually reaching the desired server, for example, unpredictable network issues. For such
cases, the api response will contain a status set to a negative number, indicating that
an exception was thrown.
```js
{
ok: false,
status: -1,
data: undefined,
}
```
### Using Apity with await syntax in templates
Assuming you've created an `src/api.ts` from [using Apity](#using-apity) section:
```svelte
import { findPetByStatus } from 'src/api.ts'
const request = findPetByStatus({ status: 'sold' })
const petsReady = request.ready
{#await $petsReady}
Loading..
{:then resp}
{#if resp.ok}
{#each resp.data as pet}
{pet.name}
{/each}
{:else}
Error while loading pets
{/if}
{/await}
{request.reload()}}>
Reload pets
```
### Subscribing to response store
Assuming you've created an `src/api.ts` from [using Apity](#using-apity) section:
```svelte
import { findPetByStatus } from 'src/api.ts'
const request = findPetByStatus({ status: 'sold' })
let names = []
request.resp.subscribe(resp => {
if (resp.ok) {
names = resp.data.map(pet => pet.name)
}
})
{#each names as name}
{name}
{/each}
```
### Using in load functions
Fetch operations support SvelteKit's [load](https://kit.svelte.dev/docs/load#making-fetch-requests) function from `+page.ts` and `+page.server.ts`.
Assuming you've created an `src/api.ts` from [using Apity](#using-apity) section:
```ts
import { findPetByStatus } from 'src/api.ts'
export async function load({ fetch }) {
const request = findPetByStatus({ status: 'sold' })
const resp = await request.result
if (resp.ok) {
return { pets: resp.data, error: undefined }
} else {
return { pets: [], error: 'Failed to load pets' }
}
}
```
# Financial support
This project has been made possible thanks to [Cocreators](https://cocreators.ee). You can help us continue our open source work by supporting us on [Buy me a coffee](https://www.buymeacoffee.com/cocreators).
[](https://www.buymeacoffee.com/cocreators)