encore
encore copied to clipboard
TS : Generate Client, Error with input params.
I'm getting the following error -
error:
Internal compiler error [E0001]
An unhandled panic occurred in the Encore compiler: runtime error: invalid memory address or nil
pointer dereference
This is a bug in Encore and should not have occurred. Please report this issue to the Encore team
either on Github at https://github.com/encoredev/encore/issues/new and include this error.
╭─[Stack Trace]
├─▶ clientgen.Client.func1 encr.dev/internal/clientgen/client.go:65
├─▶ clientgen.(*typescript).handleBailout encr.dev/internal/clientgen/typescript.go:1534
├─▶ clientgen.(*typescript).isRecursive encr.dev/internal/clientgen/typescript.go:1624
├─▶ clientgen.(*typescript).writeTyp encr.dev/internal/clientgen/typescript.go:1492
├─▶ clientgen.(*typescript).writeService encr.dev/internal/clientgen/typescript.go:256
├─▶ clientgen.(*typescript).Generate encr.dev/internal/clientgen/typescript.go:96
╰─[... remaining frames omitted ...]
Error executing adminApiCommand: Command failed: encore gen client --services=adminApi --output=../../packages/client-encore-admin/generated/client.ts --env=local
This occurs from the example project code (https://github.com/encoredev/examples/blob/main/ts/prisma/users/user.controller.ts#L84) -
export const update = api(
{ expose: true, method: "PATCH", path: "/users/:id" },
async ({
id,
data,
}: {
id: number;
data: UpdateUserDto;
}): Promise<UserResponse> => {
try {
const result = await UserService.update(id, data);
return result;
} catch (error) {
throw APIError.aborted(error?.toString() || "Error updating user");
}
},
);
All other endpoints in that file generate without an issue.
Possible that this is a typescript/node issue -
Swapping out with -
id: number;
data: {
name?: string;
surname?: string;
};
rather than
id: number;
data: UpdateUserDto;
Seems to "fix" the issue.
I've changed this to -
async ({ id, ...data }: { id: number } & UpdateUserDto): Promise<UserResponse> => {
And now it compiles correctly.
This is potentially a change in versions? I'm using "encore.dev": "^1.45.6" while the example is using "encore.dev": "^1.39.5"
🫤 I'm still a little confused why it doesn't like the data: UpdateUserDto;
Yeah seems to not recognise the type/interface from children, this test also fails -
type Other = {
id: number;
}
async ({
id,
...data
}: { id: number; other: Other } & UpdateUserDto): Promise<UserResponse> => {...
I tried it with the latest version of encore (1.45.7), checked out the prisma example, and it generated without problems. Have you made any changes to the example code?
What is the exact command that you run when you encounter this problem in the example?
If you cant reproduce it with the example, could you share some code so that I can try to reproduce it. Specifically the type definitions would be interesting to see
This issues persists, I'm on the latest version 1.46.4. It seem to be that the issue appears when using a defined type. Some examples below.
The following example fails -
// in controller.ts (requires the workaround with {} & DefinedType), without that it fails too.
async ({ id, ...input }: { id: string} & ProjectCreationInput): Promise<ProjectResponse> => {
...
// in interface.ts
export type ProjectIcon = "ICON_01" | "ICON_02" | "ICON_03" | "ICON_04" | "ICON_05";
export interface ProjectCreationInput {
name: string;
// option 1. no matter what this fails. And this isn't really an option icon: { other?: string } & ProjectIcon;
icon: ProjectIcon;
// option 2. this works if I do the above workaround (with {} & DefinedType).
icon: "ICON_01" | "ICON_02" | "ICON_03" | "ICON_04" | "ICON_05";
}
I can confirm there are no issues with response types eg. ProjectResponse also has icon: ProjectIcon; and generates the client, with types wonderfully!
When I visit http://localhost:9400/... it seems to still recognise the types values.
This may relate to the environment (turborepo). I just tested the prisma example project, and changed the following,
export interface Other {
other: string;
}
export interface UpdateUserDto {
/** Name of the user */
name?: string;
/** Surname of the user */
surname?: string;
other: Other;
}
There was no issue in the example project but as soon as I shifted it into my project it failed.
We managed to find a work around, seems that when we define the whole type there is no issue -
type ProjectCreationUpdate = { id: string } & ProjectCreationInput;
export const projectCreationUpdate = api(
{ expose: true, auth: true, method: "PATCH", path: "/projects/:id/creation" },
async ({ id, ...input }: ProjectCreationUpdate): Promise<ProjectResponse> => {
....
}
);
Generates to -
export interface ProjectCreationUpdate {
name: string;
icon: ProjectIcon;
}
public async projectCreationUpdate(
id: string,
params: project.ProjectCreationUpdate,
): Promise<project.ProjectResponse> { ...
Here is a minimal reproduction https://github.com/gladeye/encore-clientgen-error It only happens when you use an inline type in an api definition, that type references a named type AND the name of the service does not match the name of the folder the service is in.