Skip to content
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

Add UUID Encode / Decode to Base58 for Friendlier URLS #335

Closed
jdgamble555 opened this issue Sep 24, 2022 · 2 comments
Closed

Add UUID Encode / Decode to Base58 for Friendlier URLS #335

jdgamble555 opened this issue Sep 24, 2022 · 2 comments
Labels
enhancement New feature or request

Comments

@jdgamble555
Copy link

jdgamble555 commented Sep 24, 2022

Feature request

398073a0-2859-4ff4-94ff-662a70cb15a0 <--> 86qJ3nXSvhBPUbmdaMwUeb

Which one looks more URL friendly?

It would be nice if we could encode this within our supabase-js sdk. Perhaps something like:

supabase.from('posts').select('*, author!inner(*)', { encode: ['id', 'author.id'] }).eq('id', pid);

This could be an array or a string for the UUID type(s). It would use these codes to convert back and forth between BASE58:

const DASH_REGEXP = /-/g
const BASE58 = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
const BASE = BigInt(BASE58.length)
const ONE = BigInt(1)
const ZERO = BigInt(0)
const UUID_INDEXES = [0, 8, 12, 16, 20]

// https://github.com/sagefy/uuid58

export function encode(uuid: string) {
  try {
    let b = BigInt('0x' + uuid.replace(DASH_REGEXP, ''))
    let u58 = ''
    do {
      u58 = BASE58[b % BASE as any] + u58
      b = b / BASE
    } while (b > 0)
    return u58
  } catch (e) {
    return uuid
  }
}

export function decode(uuid58: string) {
  try {
    const parts = Array.from(uuid58).map(x => BASE58.indexOf(x))
    if (parts.some(inc => inc < 0)) return uuid58
    const max = uuid58.length - 1
    const b = parts.reduce(
      (acc, inc, pos) => (acc + BigInt(inc)) * (pos < max ? BASE : ONE),
      ZERO
    )
    const hex = b.toString(16).padStart(32, '0')
    return UUID_INDEXES.map((p, i, a) => hex.substring(p, a[i + 1])).join('-')
  } catch (e) {
    return uuid58
  }
}

We would do the same thing for decoding:

supabase.from('posts').upsert(new_data, { decode: 'id' }).select().single();

Thus, friendly UUID types built-in.

J

@jdgamble555 jdgamble555 added the enhancement New feature or request label Sep 24, 2022
@CanRau
Copy link

CanRau commented Sep 25, 2022

Uuh yes please this looks really interesting

Like the syntax allowing for multiple fields to be used 👏

Also would be amazing to have pg_idkit available

Some discussion around the interest in shorter IDs: discord

@steve-chavez steve-chavez transferred this issue from supabase/supabase-js Sep 26, 2022
@soedirgo
Copy link
Member

soedirgo commented Sep 27, 2022

I don't think we'll be doing this in the client lib itself. This could be done via helper functions, e.g.:

const preProcess = (data) => {
  // decode id in data if exists
  // return data with decoded id
}
const postProcess = async (client) => {
  // const { data, error } = await client
  // encode id
  // return { data, error }
}

const { data, error } = await postProcess(
  supabase.from('my_table').select()
)

await supabase.from('my_table').insert(preProcess({ id: 'some-base58' }))

Alternatively if this could be done on the database side (e.g. with plv8 on a text primary key column) that should be preferred.

@soedirgo soedirgo closed this as not planned Won't fix, can't repro, duplicate, stale Sep 27, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants