oscklm
oscklm•14mo ago

This breaks types, and makes api / internal return any?

Hello so i just come across was was breaking api / internal types for convex in my repo: And i'm curious to learn as of why this would break it? This works:
'use node'
// ...imports
export const createVideo = action({
args: video,
handler: async (ctx, args) => {
// Create video and return the ID
const videoId = await ctx.runMutation(internal.videos.mutations.insert, args)

// Create mux upload
const upload = await client.Video.Uploads.create({
new_asset_settings: {
passthrough: videoId,
playback_policy: 'public',
max_resolution_tier: '1080p',
encoding_tier: 'smart',
mp4_support: 'standard',
},
cors_origin: '*',
})

return upload.url
},
})
'use node'
// ...imports
export const createVideo = action({
args: video,
handler: async (ctx, args) => {
// Create video and return the ID
const videoId = await ctx.runMutation(internal.videos.mutations.insert, args)

// Create mux upload
const upload = await client.Video.Uploads.create({
new_asset_settings: {
passthrough: videoId,
playback_policy: 'public',
max_resolution_tier: '1080p',
encoding_tier: 'smart',
mp4_support: 'standard',
},
cors_origin: '*',
})

return upload.url
},
})
This breaks api / internal and make them any
'use node'
// ...imports
export const createVideo = action({
args: video,
handler: async (ctx, args) => {
// Create video and return the ID
const videoId = await ctx.runMutation(internal.videos.mutations.insert, args)

// Create mux upload
const upload = await client.Video.Uploads.create({
new_asset_settings: {
passthrough: videoId,
playback_policy: 'public',
max_resolution_tier: '1080p',
encoding_tier: 'smart',
mp4_support: 'standard',
},
cors_origin: '*',
})

return {
videoId,
upload,
}
},
})
'use node'
// ...imports
export const createVideo = action({
args: video,
handler: async (ctx, args) => {
// Create video and return the ID
const videoId = await ctx.runMutation(internal.videos.mutations.insert, args)

// Create mux upload
const upload = await client.Video.Uploads.create({
new_asset_settings: {
passthrough: videoId,
playback_policy: 'public',
max_resolution_tier: '1080p',
encoding_tier: 'smart',
mp4_support: 'standard',
},
cors_origin: '*',
})

return {
videoId,
upload,
}
},
})
6 Replies
oscklm
oscklmOP•14mo ago
Furthermore explicitly typing the return of the handler, fixes the issue? and lets me return the object
interface CreateVideoResponse {
videoId: Id<'videos'>
upload: Upload
}

export const createVideo = action({
args: video,
handler: async (ctx, args): Promise<CreateVideoResponse> => {
// Create video and return the ID
const videoId = await ctx.runMutation(internal.videos.mutations.insert, args)

// Create mux upload
const upload = await client.Video.Uploads.create({
new_asset_settings: {
passthrough: videoId,
playback_policy: 'public',
max_resolution_tier: '1080p',
encoding_tier: 'smart',
mp4_support: 'standard',
},
cors_origin: '*',
})

return {
videoId,
upload,
}
},
})
interface CreateVideoResponse {
videoId: Id<'videos'>
upload: Upload
}

export const createVideo = action({
args: video,
handler: async (ctx, args): Promise<CreateVideoResponse> => {
// Create video and return the ID
const videoId = await ctx.runMutation(internal.videos.mutations.insert, args)

// Create mux upload
const upload = await client.Video.Uploads.create({
new_asset_settings: {
passthrough: videoId,
playback_policy: 'public',
max_resolution_tier: '1080p',
encoding_tier: 'smart',
mp4_support: 'standard',
},
cors_origin: '*',
})

return {
videoId,
upload,
}
},
})
I'm so confused, because this is not the first time im returning a object from a handler? So i dont think i fully understand why the type cant get through when done without typing the return type
erquhart
erquhart•14mo ago
Yep explicit typing generally fixes this sort of thing. I've run into it a lot and still don't understand it, but I have seen more than once that directly returning the result of a query/mutation can cause this, in this case videoId being included in the returned object. Your error probably says the type is infinitely deep, which again points to some sort of recursion of types issue with returning the result of an api/internal function.
Michal Srb
Michal Srb•14mo ago
Yeah! The return type of the of the inner call comes from the api/internal - yet it is required to infer the type of the caller, which is part of the api/internal type! That's the infinite loop 😦
No description
oscklm
oscklmOP•14mo ago
Yeah def had me confused too Erquhart, thanks for chipping in with what you experienced. Now it makes more sense with the visual representation of the infinite loop that Michael drew out.
erquhart
erquhart•14mo ago
@Michal Srb specifying the function return type is pretty much the workaround here right? Just making sure there's not another way.
Michal Srb
Michal Srb•14mo ago
Yup, specifying the caller's return type is a the right way to break the cycle.

Did you find this page helpful?