Skip to content

feat: give includes basic entry and asset types instead of any #2363

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions lib/types/entry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ export type EntryCollection<
> = ContentfulCollection<Entry<EntrySkeleton, Modifiers, Locales>> & {
errors?: Array<any>
includes?: {
Entry?: any[]
Asset?: any[]
Entry?: Entry<EntrySkeletonType, Modifiers, Locales>[]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should not pass down the Locales variable here and use LocaleCode instead because linked entries might come from other spaces which can have different locales.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So when we make cross-space requests we basically don't know anymore what locales we're dealing with?
That makes sense, but won't that then also already be broken in the more common case of actually using the link resolution, since there we cannot distinguish?

I'm a bit split between making it easy for the most common use case of not having cross space links, but a set of explicit locales, and ensuring that the types aren't misleading in the case where you use cross space links to spaces with a different set of locales.

I guess since the includes are also not returned in a structure where customers could provide something like a space / locale mapping that means we basically have no way to ever really have locale types that are anything other than string.

So I'm wondering, maybe it's better to keep using Locales which will probably in much more than 90% of cases be the expected behavior, and which you can at least put all the locales between the different spaces in as a workaround, instead of forcing includes to always have untyped locales.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, you’re right. Even in most cross space cases the locales should be created to match and in cases that are more complicated the locale types probably won’t help much and have to be checked at runtime anyway in which case you would just use string and be correct.

Asset?: Asset<Modifiers, Locales>[]
}
}
191 changes: 139 additions & 52 deletions test/types/client/getEntries.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,105 +18,192 @@ type Fields = {
moreLinks: Entry<LinkedSkeleton>[]
}

type EntrySkeleton = EntrySkeletonType<Fields, 'content-type-id'>
// A skeleton with no fields
type BaseEntrySkeleton = EntrySkeletonType

// Skeleton with some specific fields
type TestEntrySkeleton = EntrySkeletonType<Fields, 'content-type-id'>

type Locale = 'en'

expectType<Entry<EntrySkeleton, undefined>>(await client.getEntry('entry-id'))
expectType<Entry<EntrySkeleton, undefined>>(await client.getEntry<EntrySkeleton>('entry-id'))
expectType<EntryCollection<EntrySkeleton, undefined>>(await client.getEntries())
expectType<EntryCollection<EntrySkeleton, undefined>>(await client.getEntries<EntrySkeleton>())
/**
* With no extra parameters
*/
expectType<Entry<TestEntrySkeleton, undefined>>(await client.getEntry('entry-id'))

expectType<Entry<TestEntrySkeleton, undefined>>(
await client.getEntry<TestEntrySkeleton>('entry-id'),
)
expectType<EntryCollection<TestEntrySkeleton, undefined>>(await client.getEntries())

expectType<EntryCollection<TestEntrySkeleton, undefined>>(
await client.getEntries<TestEntrySkeleton>(),
)
expectType<Entry<BaseEntrySkeleton, undefined>>((await client.getEntries()).includes!.Entry![0])

expectType<EntryCollection<EntrySkeleton, undefined>>(
await client.getEntries<EntrySkeleton>({ content_type: 'content-type-id' }),
expectType<EntryCollection<TestEntrySkeleton, undefined>>(
await client.getEntries<TestEntrySkeleton>({ content_type: 'content-type-id' }),
)

expectError(await client.getEntries<EntrySkeleton>({ content_type: 'unexpected' }))
expectType<EntryCollection<EntrySkeleton | LinkedSkeleton, undefined>>(
await client.getEntries<EntrySkeleton | LinkedSkeleton>({
expectError(await client.getEntries<TestEntrySkeleton>({ content_type: 'unexpected' }))

expectType<EntryCollection<TestEntrySkeleton | LinkedSkeleton, undefined>>(
await client.getEntries<TestEntrySkeleton | LinkedSkeleton>({
content_type: 'content-type-id',
}),
)

expectType<Entry<EntrySkeleton, 'WITHOUT_UNRESOLVABLE_LINKS'>>(
/**
* Without unresolvable Links
*/
expectType<Entry<TestEntrySkeleton, 'WITHOUT_UNRESOLVABLE_LINKS'>>(
await client.withoutUnresolvableLinks.getEntry('entry-id'),
)
expectType<Entry<EntrySkeleton, 'WITHOUT_UNRESOLVABLE_LINKS'>>(
await client.withoutUnresolvableLinks.getEntry<EntrySkeleton>('entry-id'),
expectType<Entry<TestEntrySkeleton, 'WITHOUT_UNRESOLVABLE_LINKS'>>(
await client.withoutUnresolvableLinks.getEntry<TestEntrySkeleton>('entry-id'),
)
expectType<EntryCollection<EntrySkeleton, 'WITHOUT_UNRESOLVABLE_LINKS'>>(

expectType<EntryCollection<TestEntrySkeleton, 'WITHOUT_UNRESOLVABLE_LINKS'>>(
await client.withoutUnresolvableLinks.getEntries(),
)
expectType<EntryCollection<EntrySkeleton, 'WITHOUT_UNRESOLVABLE_LINKS'>>(
await client.withoutUnresolvableLinks.getEntries<EntrySkeleton>(),

expectType<EntryCollection<TestEntrySkeleton, 'WITHOUT_UNRESOLVABLE_LINKS'>>(
await client.withoutUnresolvableLinks.getEntries<TestEntrySkeleton>(),
)

expectType<Entry<EntrySkeleton, 'WITHOUT_LINK_RESOLUTION'>>(
expectType<Entry<BaseEntrySkeleton, 'WITHOUT_UNRESOLVABLE_LINKS'>>(
(await client.withoutUnresolvableLinks.getEntries()).includes!.Entry![0],
)

/**
* Without link resolution
*/
expectType<Entry<TestEntrySkeleton, 'WITHOUT_LINK_RESOLUTION'>>(
await client.withoutLinkResolution.getEntry('entry-id'),
)
expectType<Entry<EntrySkeleton, 'WITHOUT_LINK_RESOLUTION'>>(
await client.withoutLinkResolution.getEntry<EntrySkeleton>('entry-id'),

expectType<Entry<TestEntrySkeleton, 'WITHOUT_LINK_RESOLUTION'>>(
await client.withoutLinkResolution.getEntry<TestEntrySkeleton>('entry-id'),
)
expectType<EntryCollection<EntrySkeleton, 'WITHOUT_LINK_RESOLUTION'>>(

expectType<EntryCollection<TestEntrySkeleton, 'WITHOUT_LINK_RESOLUTION'>>(
await client.withoutLinkResolution.getEntries(),
)
expectType<EntryCollection<EntrySkeleton, 'WITHOUT_LINK_RESOLUTION'>>(
await client.withoutLinkResolution.getEntries<EntrySkeleton>(),

expectType<EntryCollection<TestEntrySkeleton, 'WITHOUT_LINK_RESOLUTION'>>(
await client.withoutLinkResolution.getEntries<TestEntrySkeleton>(),
)

expectType<Entry<EntrySkeleton, 'WITH_ALL_LOCALES'>>(
expectType<Entry<BaseEntrySkeleton, 'WITHOUT_LINK_RESOLUTION'>>(
(await client.withoutLinkResolution.getEntries()).includes!.Entry![0],
)

/**
* With all Locales
*/
expectType<Entry<TestEntrySkeleton, 'WITH_ALL_LOCALES'>>(
await client.withAllLocales.getEntry('entry-id'),
)
expectType<Entry<EntrySkeleton, 'WITH_ALL_LOCALES'>>(
await client.withAllLocales.getEntry<EntrySkeleton>('entry-id'),

expectType<Entry<TestEntrySkeleton, 'WITH_ALL_LOCALES'>>(
await client.withAllLocales.getEntry<TestEntrySkeleton>('entry-id'),
)
expectType<Entry<EntrySkeleton, 'WITH_ALL_LOCALES', Locale>>(
await client.withAllLocales.getEntry<EntrySkeleton, Locale>('entry-id'),

expectType<Entry<TestEntrySkeleton, 'WITH_ALL_LOCALES', Locale>>(
await client.withAllLocales.getEntry<TestEntrySkeleton, Locale>('entry-id'),
)
expectType<EntryCollection<EntrySkeleton, 'WITH_ALL_LOCALES'>>(

expectType<EntryCollection<TestEntrySkeleton, 'WITH_ALL_LOCALES'>>(
await client.withAllLocales.getEntries(),
)
expectType<EntryCollection<EntrySkeleton, 'WITH_ALL_LOCALES'>>(
await client.withAllLocales.getEntries<EntrySkeleton>(),

expectType<EntryCollection<TestEntrySkeleton, 'WITH_ALL_LOCALES'>>(
await client.withAllLocales.getEntries<TestEntrySkeleton>(),
)

expectType<EntryCollection<TestEntrySkeleton, 'WITH_ALL_LOCALES', Locale>>(
await client.withAllLocales.getEntries<TestEntrySkeleton, Locale>(),
)

expectType<Entry<BaseEntrySkeleton, 'WITH_ALL_LOCALES', Locale>>(
(await client.withAllLocales.getEntries<TestEntrySkeleton, Locale>()).includes!.Entry![0],
)
expectType<EntryCollection<EntrySkeleton, 'WITH_ALL_LOCALES', Locale>>(
await client.withAllLocales.getEntries<EntrySkeleton, Locale>(),

expectType<Entry<BaseEntrySkeleton, 'WITH_ALL_LOCALES'>>(
(await client.withAllLocales.getEntries<TestEntrySkeleton>()).includes!.Entry![0],
)

expectType<Entry<EntrySkeleton, 'WITH_ALL_LOCALES' | 'WITHOUT_UNRESOLVABLE_LINKS'>>(
/**
* With all Locales and without unresolvable Links
*/
expectType<Entry<TestEntrySkeleton, 'WITH_ALL_LOCALES' | 'WITHOUT_UNRESOLVABLE_LINKS'>>(
await client.withAllLocales.withoutUnresolvableLinks.getEntry('entry-id'),
)
expectType<Entry<EntrySkeleton, 'WITH_ALL_LOCALES' | 'WITHOUT_UNRESOLVABLE_LINKS'>>(
await client.withAllLocales.withoutUnresolvableLinks.getEntry<EntrySkeleton>('entry-id'),

expectType<Entry<TestEntrySkeleton, 'WITH_ALL_LOCALES' | 'WITHOUT_UNRESOLVABLE_LINKS'>>(
await client.withAllLocales.withoutUnresolvableLinks.getEntry<TestEntrySkeleton>('entry-id'),
)
expectType<Entry<EntrySkeleton, 'WITH_ALL_LOCALES' | 'WITHOUT_UNRESOLVABLE_LINKS', Locale>>(
await client.withAllLocales.withoutUnresolvableLinks.getEntry<EntrySkeleton, Locale>('entry-id'),

expectType<Entry<TestEntrySkeleton, 'WITH_ALL_LOCALES' | 'WITHOUT_UNRESOLVABLE_LINKS', Locale>>(
await client.withAllLocales.withoutUnresolvableLinks.getEntry<TestEntrySkeleton, Locale>(
'entry-id',
),
)
expectType<EntryCollection<EntrySkeleton, 'WITH_ALL_LOCALES' | 'WITHOUT_UNRESOLVABLE_LINKS'>>(

expectType<EntryCollection<TestEntrySkeleton, 'WITH_ALL_LOCALES' | 'WITHOUT_UNRESOLVABLE_LINKS'>>(
await client.withAllLocales.withoutUnresolvableLinks.getEntries(),
)
expectType<EntryCollection<EntrySkeleton, 'WITH_ALL_LOCALES' | 'WITHOUT_UNRESOLVABLE_LINKS'>>(
await client.withAllLocales.withoutUnresolvableLinks.getEntries<EntrySkeleton>(),

expectType<EntryCollection<TestEntrySkeleton, 'WITH_ALL_LOCALES' | 'WITHOUT_UNRESOLVABLE_LINKS'>>(
await client.withAllLocales.withoutUnresolvableLinks.getEntries<TestEntrySkeleton>(),
)

expectType<
EntryCollection<EntrySkeleton, 'WITH_ALL_LOCALES' | 'WITHOUT_UNRESOLVABLE_LINKS', Locale>
>(await client.withAllLocales.withoutUnresolvableLinks.getEntries<EntrySkeleton, Locale>())
EntryCollection<TestEntrySkeleton, 'WITH_ALL_LOCALES' | 'WITHOUT_UNRESOLVABLE_LINKS', Locale>
>(await client.withAllLocales.withoutUnresolvableLinks.getEntries<TestEntrySkeleton, Locale>())

expectType<Entry<EntrySkeleton, 'WITH_ALL_LOCALES' | 'WITHOUT_LINK_RESOLUTION'>>(
expectType<Entry<BaseEntrySkeleton, 'WITH_ALL_LOCALES' | 'WITHOUT_UNRESOLVABLE_LINKS'>>(
(await client.withAllLocales.withoutUnresolvableLinks.getEntries<TestEntrySkeleton>()).includes!
.Entry![0],
)

expectType<Entry<BaseEntrySkeleton, 'WITH_ALL_LOCALES' | 'WITHOUT_UNRESOLVABLE_LINKS', Locale>>(
(await client.withAllLocales.withoutUnresolvableLinks.getEntries<TestEntrySkeleton, Locale>())
.includes!.Entry![0],
)

/**
* With all Locales and without link resolution
*/
expectType<Entry<TestEntrySkeleton, 'WITH_ALL_LOCALES' | 'WITHOUT_LINK_RESOLUTION'>>(
await client.withAllLocales.withoutLinkResolution.getEntry('entry-id'),
)
expectType<Entry<EntrySkeleton, 'WITH_ALL_LOCALES' | 'WITHOUT_LINK_RESOLUTION'>>(
await client.withAllLocales.withoutLinkResolution.getEntry<EntrySkeleton>('entry-id'),

expectType<Entry<TestEntrySkeleton, 'WITH_ALL_LOCALES' | 'WITHOUT_LINK_RESOLUTION'>>(
await client.withAllLocales.withoutLinkResolution.getEntry<TestEntrySkeleton>('entry-id'),
)
expectType<Entry<EntrySkeleton, 'WITH_ALL_LOCALES' | 'WITHOUT_LINK_RESOLUTION', Locale>>(
await client.withAllLocales.withoutLinkResolution.getEntry<EntrySkeleton, Locale>('entry-id'),

expectType<Entry<TestEntrySkeleton, 'WITH_ALL_LOCALES' | 'WITHOUT_LINK_RESOLUTION', Locale>>(
await client.withAllLocales.withoutLinkResolution.getEntry<TestEntrySkeleton, Locale>('entry-id'),
)
expectType<EntryCollection<EntrySkeleton, 'WITH_ALL_LOCALES' | 'WITHOUT_LINK_RESOLUTION'>>(

expectType<EntryCollection<TestEntrySkeleton, 'WITH_ALL_LOCALES' | 'WITHOUT_LINK_RESOLUTION'>>(
await client.withAllLocales.withoutLinkResolution.getEntries(),
)
expectType<EntryCollection<EntrySkeleton, 'WITH_ALL_LOCALES' | 'WITHOUT_LINK_RESOLUTION'>>(
await client.withAllLocales.withoutLinkResolution.getEntries<EntrySkeleton>(),

expectType<EntryCollection<TestEntrySkeleton, 'WITH_ALL_LOCALES' | 'WITHOUT_LINK_RESOLUTION'>>(
await client.withAllLocales.withoutLinkResolution.getEntries<TestEntrySkeleton>(),
)

expectType<
EntryCollection<TestEntrySkeleton, 'WITH_ALL_LOCALES' | 'WITHOUT_LINK_RESOLUTION', Locale>
>(await client.withAllLocales.withoutLinkResolution.getEntries<TestEntrySkeleton, Locale>())

expectType<Entry<BaseEntrySkeleton, 'WITH_ALL_LOCALES' | 'WITHOUT_LINK_RESOLUTION'>>(
(await client.withAllLocales.withoutLinkResolution.getEntries()).includes!.Entry![0],
)
expectType<EntryCollection<EntrySkeleton, 'WITH_ALL_LOCALES' | 'WITHOUT_LINK_RESOLUTION', Locale>>(
await client.withAllLocales.withoutLinkResolution.getEntries<EntrySkeleton, Locale>(),

expectType<Entry<BaseEntrySkeleton, 'WITH_ALL_LOCALES' | 'WITHOUT_LINK_RESOLUTION', Locale>>(
(await client.withAllLocales.withoutLinkResolution.getEntries<TestEntrySkeleton, Locale>())
.includes!.Entry![0],
)