Skip to content

typescript incompatibility upgrading from @supabase/ssr 0.5.2 to 0.6.1 #106

@khera

Description

@khera

Bug report

  • I confirm this is a bug with Supabase, not with my own application.
  • I confirm I have searched the Docs, GitHub Discussions, and Discord.

Describe the bug

The ssr library changed the return value of the parseCookieHeader() function to be incompatible with what is expected to be returned from the getAll() cookie function. The example code from the guide no longer is clean typescript.

To Reproduce

My app is built with Remix v2 and the ssr code is copy/pasted from the guide.

I store the client object in a structure I keep in an AsyncLocalContext to isolate my API route invocations from each other. The structure in the context is this:

type supabaseConnectionType = {
  supabase?: SupabaseClient<Database>;
  supabase_is_admin?: boolean;
};

And the code that creates the client (copy/pasted from the guide, basically):

  supabaseConnection.supabase = createServerClient<Database>(process.env.SUPABASE_URL!, process.env.SUPABASE_ANON_KEY!,
    {
      cookies: {
        getAll() {
          return parseCookieHeader(request.headers.get('Cookie') ?? '')
        },
        setAll(cookiesToSet) {
          cookiesToSet.forEach(({ name, value, options }) =>
            headers.append('Set-Cookie', serializeCookieHeader(name, value, options))
          )
        },
      },
    },
  );

First issue I have is that the type now returned from createServerClient() is not compatible with the declared type for my variable anymore:

error TS2322: Type 'SupabaseClient<Database, "public" extends keyof Database ? "public" : string & keyof Database, Database[SchemaName] extends GenericSchema ? Database[SchemaName] : any>' is not assignable to type 'SupabaseClient<Database, "public", { Tables: { content_planner: { Row: { content_id: string; content_keywords: string[] | null; content_persona: string | null; content_rationale: string | null; ... 9 more ...; used_time: string | null; }; Insert: { ...; }; Update: { ...; }; Relationships: [...]; }; ... 5 more ...; u...'.
  Type '"public" extends keyof Database ? "public" : string & keyof Database' is not assignable to type '"public"'.
    Type '"public" | (string & keyof Database)' is not assignable to type '"public"'.
      Type 'string & keyof Database' is not assignable to type '"public"'.

Second issue is it does not like the return type of getAll(), from overload 2. This is because the parseCookieHeader() now makes the value optional. This error in turn labels the createServerClient() method itself as deprecated, which is what triggers the first typescript complaint.

error TS2769: No overload matches this call.
  Overload 1 of 2, '(supabaseUrl: string, supabaseKey: string, options: SupabaseClientOptions<"public"> & { cookieOptions?: CookieOptionsWithName | undefined; cookies: CookieMethodsServerDeprecated; cookieEncoding?: "raw" | ... 1 more ... | undefined; }): SupabaseClient<...>', gave the following error.
    Object literal may only specify known properties, and 'getAll' does not exist in type 'CookieMethodsServerDeprecated'.
  Overload 2 of 2, '(supabaseUrl: string, supabaseKey: string, options: SupabaseClientOptions<"public"> & { cookieOptions?: CookieOptionsWithName | undefined; cookies: CookieMethodsServer; cookieEncoding?: "raw" | ... 1 more ... | undefined; }): SupabaseClient<...>', gave the following error.
    Type '() => { name: string; value?: string | undefined; }[]' is not assignable to type 'GetAllCookies'.
      Type '{ name: string; value?: string | undefined; }[]' is not assignable to type 'Promise<{ name: string; value: string; }[] | null> | { name: string; value: string; }[] | null'.
        Type '{ name: string; value?: string | undefined; }[]' is not assignable to type '{ name: string; value: string; }[]'.
          Type '{ name: string; value?: string | undefined; }' is not assignable to type '{ name: string; value: string; }'.
            Types of property 'value' are incompatible.
              Type 'string | undefined' is not assignable to type 'string'.
                Type 'undefined' is not assignable to type 'string'.

The workaround to both of these issue (conveniently) is to convert missing value to empty string in getAll(). I suppose we could also just remove any cookie without a value as they are useless.

          return parseCookieHeader(request.headers.get('Cookie') ?? '').map(({ name, value }) => ({
            name,
            value: value ?? '',
          }))

Expected behavior

The types should be consistent.

The correct fix, I believe, is to make the expected return type signature from getAll() consistent with that of the parseCookieHeader() function, whether it be updating the signature, or reverting the parseCookieHeader() value field to be required.

Screenshots

If applicable, add screenshots to help explain your problem.

System information

  • OS: [e.g. macOS, Windows] macOS
  • Browser (if applies) [e.g. chrome, safari]
  • Version of supabase-js: [e.g. 6.0.2] 2.49.4
  • Version of Node.js: [e.g. 10.10.0] v23.11.0
  • [email protected]

Additional context

Add any other context about the problem here.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions