feat(dx): [WIP] auto-generate correctly typed client for any API route 🎉
This commit is contained in:
parent
01ed8cfb12
commit
30493ade84
|
@ -9,6 +9,7 @@ import { humanSize, truncate } from '~/utils/filters'
|
|||
import { useI18n } from 'vue-i18n'
|
||||
import { sortBy } from 'lodash-es'
|
||||
import { useStore } from '~/store'
|
||||
import { useClient } from '~/ui/composables/useClient'
|
||||
|
||||
import axios from 'axios'
|
||||
|
||||
|
@ -41,6 +42,7 @@ const props = withDefaults(defineProps<Props>(), {
|
|||
|
||||
const { t } = useI18n()
|
||||
const store = useStore()
|
||||
const { get, post } = useClient('libraries')
|
||||
|
||||
const upload = ref()
|
||||
const currentTab = ref('uploads')
|
||||
|
@ -80,6 +82,23 @@ const options = {
|
|||
|
||||
const privacyLevel = defineModel<keyof typeof options>({ required: true })
|
||||
|
||||
// New implementation with `useClient`:
|
||||
|
||||
watch(privacyLevel, (newValue) =>
|
||||
get({
|
||||
query: {
|
||||
privacy_level: newValue,
|
||||
scope: 'me'
|
||||
}
|
||||
})
|
||||
.then((data) =>
|
||||
library.value = data?.results.find(({name}) => name === privacyLevel.value)
|
||||
),
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
// Old implementation:
|
||||
/*
|
||||
const library = ref<Library>()
|
||||
watch(privacyLevel, async(newValue) => { try {
|
||||
const response = await axios.get<paths['/api/v2/libraries/']['get']['responses']['200']['content']['application/json']>('libraries/', {
|
||||
|
@ -93,6 +112,7 @@ watch(privacyLevel, async(newValue) => { try {
|
|||
} catch (error) {
|
||||
useErrorHandler(error as Error)
|
||||
}}, { immediate: true })
|
||||
*/
|
||||
|
||||
//
|
||||
// File counts
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
import { type paths } from '~/generated/types.ts'
|
||||
import { type Simplify } from 'type-fest'
|
||||
|
||||
import axios from 'axios'
|
||||
import useErrorHandler from '~/composables/useErrorHandler'
|
||||
|
||||
const prefix = "/api/v2/" as const;
|
||||
type Prefix = typeof prefix;
|
||||
|
||||
type RemovePrefixAndSuffix<T extends string> =
|
||||
T extends `${Prefix}${infer Infix}/` ? Infix : never
|
||||
|
||||
type Path = RemovePrefixAndSuffix<Simplify<keyof paths>>
|
||||
|
||||
type Get<TPath extends Path> = paths[`${Prefix}${TPath}/`]['get']
|
||||
type Post<TPath extends Path> = paths[`${Prefix}${TPath}/`]['post']
|
||||
|
||||
type GetRequestParameters<TPath extends Path> =
|
||||
Get<TPath> extends { parameters: any }
|
||||
? Get<TPath>['parameters']
|
||||
: never
|
||||
|
||||
/**
|
||||
* 200
|
||||
*/
|
||||
type OK<TPath extends Path> =
|
||||
Get<TPath> extends { responses: { ['200'] : { content: { ['application/json']: any } } } }
|
||||
? Get<TPath>['responses']['200']['content']['application/json']
|
||||
: never
|
||||
|
||||
type PostRequestJson<TPath extends Path> =
|
||||
Post<TPath> extends { requestBody: { content: { ['application/json']: any } } }
|
||||
? Post<TPath>['requestBody']['content']['application/json']
|
||||
: never
|
||||
|
||||
/**
|
||||
* 201
|
||||
*/
|
||||
type Created<TPath extends Path> =
|
||||
Post<TPath> extends { responses: { ['201']: { content: { ['application/json']: any } } } }
|
||||
? Post<TPath>['responses']['201']['content']['application/json']
|
||||
: never
|
||||
|
||||
/**
|
||||
*
|
||||
* Returns `get` and `post` clients for the chosen path (endpoint).
|
||||
```ts
|
||||
const { get, post } = useClient('manage/tags');
|
||||
|
||||
const result0 = post({ name: 'test' })
|
||||
const result1 = get({ query: { q: 'test' } })
|
||||
```
|
||||
*
|
||||
* @param path The path to create a client for. Check the `paths` type in '~/generated/types.ts' to find all available paths.
|
||||
*/
|
||||
export const useClient = <TPath extends Path>( path: TPath ) => ({
|
||||
|
||||
get: async (parameters: GetRequestParameters<TPath>) =>
|
||||
await axios.get<OK<TPath>>(`${prefix}${path}/`, {
|
||||
params: parameters.query || parameters
|
||||
})
|
||||
.then(({ data }) => { return data })
|
||||
.catch (useErrorHandler),
|
||||
|
||||
post: async (requestBody: PostRequestJson<TPath> ) =>
|
||||
await axios.post<Created<TPath>>(`${prefix}${path}/`, {
|
||||
params: requestBody
|
||||
})
|
||||
.then(({ data }) => { return data })
|
||||
.catch (useErrorHandler)
|
||||
|
||||
// TODO: Add put, patch, delete, head, options, trace
|
||||
|
||||
})
|
Loading…
Reference in New Issue