Skip to content

Commit 8838d55

Browse files
feat(useStrapi): improve types for v5 and v4 (#445)
Co-authored-by: Benjamin Canac <[email protected]>
1 parent 9572f7b commit 8838d55

File tree

7 files changed

+83
-25
lines changed

7 files changed

+83
-25
lines changed

playground/nuxt.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export default defineNuxtConfig({
1414
// },
1515

1616
strapi: {
17-
version: 'v3',
17+
version: 'v5',
1818
url: 'http://localhost:1337'
1919
// To enable the devtools, read https://strapi.nuxtjs.org/devtools
2020
// devtools: true

playground/pages/index.vue

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,20 @@
77
<h2>Version</h2>
88
<pre>{{ version }}</pre>
99

10+
<h2>API</h2>
11+
<button
12+
type="button"
13+
@click="getCollections"
14+
>
15+
Get collections
16+
</button>
17+
<button
18+
type="button"
19+
@click="getUntyped"
20+
>
21+
Get untyped
22+
</button>
23+
1024
<div v-if="user">
1125
<h2>User</h2>
1226
<button
@@ -52,6 +66,7 @@
5266
</template>
5367

5468
<script lang="ts" setup>
69+
const strapi = useStrapi()
5570
const user = useStrapiUser()
5671
const url = useStrapiUrl()
5772
const version = useStrapiVersion()
@@ -60,6 +75,33 @@ const { login, logout, getProviderAuthenticationUrl } = useStrapiAuth()
6075
const loading = ref(false)
6176
const form = reactive({ identifier: '', password: '' })
6277
78+
type Collection = {
79+
firstname: string
80+
lastname: string
81+
relation: {
82+
name: string
83+
nestedRelation: {
84+
name: string
85+
arr: Array<{ name: string }>
86+
}
87+
}
88+
}
89+
90+
const getCollections = () => {
91+
return strapi.find<Collection>('collection', {
92+
fields: ['firstname'],
93+
sort: ['lastname:asc', 'firstname'],
94+
populate: 'relation.nestedRelation.arr'
95+
})
96+
}
97+
98+
const getUntyped = () => {
99+
return strapi.find('untyped', {
100+
sort: ['random'],
101+
populate: 'relationRandom'
102+
})
103+
}
104+
63105
const onSubmit = async () => {
64106
loading.value = true
65107

src/runtime/composables-v4/useStrapi.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ import type { Strapi4ResponseSingle, Strapi4RequestParams, Strapi4ResponseMany }
33
import { useStrapiClient } from '#imports'
44

55
interface StrapiV4Client<T> {
6-
find<F = T>(contentType: string, params?: Strapi4RequestParams): Promise<Strapi4ResponseMany<F>>
7-
findOne<F = T>(contentType: string, id?: string | number | Strapi4RequestParams, params?: Strapi4RequestParams): Promise<Strapi4ResponseSingle<F>>
6+
find<F = T>(contentType: string, params?: Strapi4RequestParams<F>): Promise<Strapi4ResponseMany<F>>
7+
findOne<F = T>(contentType: string, id?: string | number | Strapi4RequestParams<F>, params?: Strapi4RequestParams<F>): Promise<Strapi4ResponseSingle<F>>
88
create<F = T>(contentType: string, data: Partial<F>): Promise<Strapi4ResponseSingle<F>>
99
update<F = T>(contentType: string, id: string | number | Partial<F>, data?: Partial<F>): Promise<Strapi4ResponseSingle<F>>
1010
delete<F = T>(contentType: string, id?: string | number): Promise<Strapi4ResponseSingle<F>>
@@ -20,7 +20,7 @@ export const useStrapi = <T>(): StrapiV4Client<T> => {
2020
* @param {Strapi4RequestParams} [params] - Query parameters
2121
* @returns Promise<T>
2222
*/
23-
const find = <T>(contentType: string, params?: Strapi4RequestParams, fetchOptions?: FetchOptions): Promise<Strapi4ResponseMany<T>> => {
23+
const find = <T>(contentType: string, params?: Strapi4RequestParams<T>, fetchOptions?: FetchOptions): Promise<Strapi4ResponseMany<T>> => {
2424
return client(`/${contentType}`, { method: 'GET', params, ...fetchOptions })
2525
}
2626

@@ -32,7 +32,7 @@ export const useStrapi = <T>(): StrapiV4Client<T> => {
3232
* @param {Strapi4RequestParams} [params] - Query parameters
3333
* @returns Promise<T>
3434
*/
35-
const findOne = <T>(contentType: string, id?: string | number | Strapi4RequestParams, params?: Strapi4RequestParams, fetchOptions?: FetchOptions): Promise<Strapi4ResponseSingle<T>> => {
35+
const findOne = <T>(contentType: string, id?: string | number | Strapi4RequestParams<T>, params?: Strapi4RequestParams<T>, fetchOptions?: FetchOptions): Promise<Strapi4ResponseSingle<T>> => {
3636
if (typeof id === 'object') {
3737
params = id
3838
id = undefined

src/runtime/composables-v5/useStrapi.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ import type { Strapi5ResponseSingle, Strapi5RequestParams, Strapi5ResponseMany }
33
import { useStrapiClient } from '#imports'
44

55
interface StrapiV5Client<T> {
6-
find<F = T>(contentType: string, params?: Strapi5RequestParams): Promise<Strapi5ResponseMany<F>>
7-
findOne<F = T>(contentType: string, documentId?: string | Strapi5RequestParams, params?: Strapi5RequestParams): Promise<Strapi5ResponseSingle<F>>
6+
find<F = T>(contentType: string, params?: Strapi5RequestParams<F>): Promise<Strapi5ResponseMany<F>>
7+
findOne<F = T>(contentType: string, documentId?: string | Strapi5RequestParams<F>, params?: Strapi5RequestParams<F>): Promise<Strapi5ResponseSingle<F>>
88
create<F = T>(contentType: string, data: Partial<F>): Promise<Strapi5ResponseSingle<F>>
99
update<F = T>(contentType: string, documentId: string | Partial<F>, data?: Partial<F>): Promise<Strapi5ResponseSingle<F>>
1010
delete<F = T>(contentType: string, documentId?: string): Promise<Strapi5ResponseSingle<F>>
@@ -17,10 +17,10 @@ export const useStrapi = <T>(): StrapiV5Client<T> => {
1717
* Get a list of {content-type} entries
1818
*
1919
* @param {string} contentType - Content type's name pluralized
20-
* @param {Strapi5RequestParams} [params] - Query parameters
20+
* @param {Strapi5RequestParams<T>} [params] - Query parameters
2121
* @returns Promise<T>
2222
*/
23-
const find = <T>(contentType: string, params?: Strapi5RequestParams, fetchOptions?: FetchOptions): Promise<Strapi5ResponseMany<T>> => {
23+
const find = <T>(contentType: string, params?: Strapi5RequestParams<T>, fetchOptions?: FetchOptions): Promise<Strapi5ResponseMany<T>> => {
2424
return client(`/${contentType}`, { method: 'GET', params, ...fetchOptions })
2525
}
2626

@@ -29,10 +29,10 @@ export const useStrapi = <T>(): StrapiV5Client<T> => {
2929
*
3030
* @param {string} contentType - Content type's name pluralized
3131
* @param {string} documentId - ID of entry
32-
* @param {Strapi5RequestParams} [params] - Query parameters
32+
* @param {Strapi5RequestParams<T>} [params] - Query parameters
3333
* @returns Promise<T>
3434
*/
35-
const findOne = <T>(contentType: string, documentId?: string | Strapi5RequestParams, params?: Strapi5RequestParams, fetchOptions?: FetchOptions): Promise<Strapi5ResponseSingle<T>> => {
35+
const findOne = <T>(contentType: string, documentId?: string | Strapi5RequestParams<T>, params?: Strapi5RequestParams<T>, fetchOptions?: FetchOptions): Promise<Strapi5ResponseSingle<T>> => {
3636
if (typeof documentId === 'object') {
3737
params = documentId
3838
documentId = undefined
@@ -48,10 +48,10 @@ export const useStrapi = <T>(): StrapiV5Client<T> => {
4848
*
4949
* @param {string} contentType - Content type's name pluralized
5050
* @param {Record<string, any>} data - Form data
51-
* @param {Strapi5RequestParams} [params] - Query parameters
51+
* @param {Strapi5RequestParams<T>} [params] - Query parameters
5252
* @returns Promise<T>
5353
*/
54-
const create = <T>(contentType: string, data: Partial<T>, params: Strapi5RequestParams = {}): Promise<Strapi5ResponseSingle<T>> => {
54+
const create = <T>(contentType: string, data: Partial<T>, params: Strapi5RequestParams<T> = {}): Promise<Strapi5ResponseSingle<T>> => {
5555
return client(`/${contentType}`, { method: 'POST', body: { data }, params })
5656
}
5757

@@ -61,10 +61,10 @@ export const useStrapi = <T>(): StrapiV5Client<T> => {
6161
* @param {string} contentType - Content type's name pluralized
6262
* @param {string} documentId - ID of entry to be updated
6363
* @param {Record<string, any>} data - Form data
64-
* @param {Strapi5RequestParams} [params] - Query parameters
64+
* @param {Strapi5RequestParams<T>} [params] - Query parameters
6565
* @returns Promise<T>
6666
*/
67-
const update = <T>(contentType: string, documentId: string | Partial<T>, data?: Partial<T>, params: Strapi5RequestParams = {}): Promise<Strapi5ResponseSingle<T>> => {
67+
const update = <T>(contentType: string, documentId: string | Partial<T>, data?: Partial<T>, params: Strapi5RequestParams<T> = {}): Promise<Strapi5ResponseSingle<T>> => {
6868
if (typeof documentId === 'object') {
6969
data = documentId
7070
documentId = undefined

src/runtime/types/index.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -570,6 +570,22 @@ export interface StrapiGraphqlVariables {
570570
[variable: string]: unknown
571571
}
572572

573+
export type StrapiRequestParamField<T> = {
574+
[K in keyof T]: T[K] extends object
575+
? never
576+
: K;
577+
}[keyof T]
578+
579+
export type StrapiRequestParamSort<T> = `${Exclude<keyof T, symbol>}${':asc' | ':desc' | ''}`
580+
581+
export type StrapiRequestParamPopulate<T> = {
582+
[K in keyof T]: T[K] extends object
583+
? T[K] extends Array<infer I>
584+
? `${Exclude<K, symbol>}` | `${Exclude<K, symbol>}.${StrapiRequestParamPopulate<I>}`
585+
: `${Exclude<K, symbol>}` | `${Exclude<K, symbol>}.${StrapiRequestParamPopulate<T[K]>}`
586+
: never;
587+
}[keyof T]
588+
573589
export * from './v3'
574590
export * from './v4'
575591
export * from './v5'

src/runtime/types/v4.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { StrapiLocale } from '.'
1+
import type { StrapiLocale, StrapiRequestParamField, StrapiRequestParamPopulate, StrapiRequestParamSort } from '.'
22

33
export interface Strapi4Error {
44
error: {
@@ -21,10 +21,10 @@ export interface PaginationByOffset {
2121
withCount?: boolean
2222
}
2323

24-
export interface Strapi4RequestParams {
25-
fields?: Array<string>
26-
populate?: string | Array<string> | object
27-
sort?: string | Array<string>
24+
export interface Strapi4RequestParams<T> {
25+
fields?: Array<StrapiRequestParamField<T>>
26+
populate?: '*' | StrapiRequestParamPopulate<T> | Array<StrapiRequestParamPopulate<T>>
27+
sort?: StrapiRequestParamSort<T> | Array<StrapiRequestParamSort<T>>
2828
pagination?: PaginationByOffset | PaginationByPage
2929
filters?: Record<string, unknown>
3030
publicationState?: 'live' | 'preview'

src/runtime/types/v5.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { MetaResponsePaginationByOffset, MetaResponsePaginationByPage, PaginationByOffset, PaginationByPage, StrapiLocale } from '.'
1+
import type { MetaResponsePaginationByOffset, MetaResponsePaginationByPage, PaginationByOffset, PaginationByPage, StrapiLocale, StrapiRequestParamField, StrapiRequestParamPopulate, StrapiRequestParamSort } from '.'
22

33
export interface Strapi5Error {
44
error: {
@@ -9,10 +9,10 @@ export interface Strapi5Error {
99
}
1010
}
1111

12-
export interface Strapi5RequestParams {
13-
fields?: Array<string>
14-
populate?: string | Array<string> | object
15-
sort?: string | Array<string>
12+
export interface Strapi5RequestParams<T> {
13+
fields?: Array<StrapiRequestParamField<T>>
14+
populate?: '*' | StrapiRequestParamPopulate<T> | Array<StrapiRequestParamPopulate<T>>
15+
sort?: StrapiRequestParamSort<T> | Array<StrapiRequestParamSort<T>>
1616
pagination?: PaginationByOffset | PaginationByPage
1717
filters?: Record<string, unknown>
1818
status?: 'published' | 'draft'

0 commit comments

Comments
 (0)