typeid

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 19, 2023 License: Apache-2.0 Imports: 7 Imported by: 0

README

TypeID Go

A golang implementation of TypeIDs

Go Reference

TypeIDs are a modern, type-safe, globally unique identifier based on the upcoming UUIDv7 standard. They provide a ton of nice properties that make them a great choice as the primary identifiers for your data in a database, APIs, and distributed systems. Read more about TypeIDs in their spec.

This particular implementation provides a go library for generating and parsing TypeIDs.

Installation

To add this library as a dependency in your go module, run:

go get go.jetpack.io/typeid

Usage

This library provides a go implementation of TypeID that allows you to define your own custom id types for added compile-time safety.

If you don't need compile-time safety, you can use the provided typeid.AnyID directly:

import (
  "go.jetpack.io/typeid"
)

func example() {
  tid, _ := typeid.WithPrefix("user")
  fmt.Println(tid)
}

If you want compile-time safety, define your own custom types with two steps:

  1. Define a struct the implements the method Prefix. Prefix should return the string that should be used as the prefix for your custom type.
  2. Define you own id type, by embedding typeid.TypeID[CustomPrefix]

For example to define a UserID with prefix user:

import (
  "go.jetpack.io/typeid"
)

// Define the prefix:
type UserPrefix struct {}
func (UserPrefix) Prefix() string { return "user" }

// Define UserID:
type UserID struct {
	typeid.TypeID[UserPrefix]
}

Now you can use the UserID type to generate new ids:

import (
  "go.jetpack.io/typeid"
)

func example() {
  tid, _ := typeid.New[UserID]()
  fmt.Println(tid)
}

For the full documentation, see this package's godoc.

Documentation

Overview

This particular implementation provides a go library for generating and parsing TypeIDs

Example
package main

import (
	"fmt"

	"go.jetpack.io/typeid"
)

// To create a new id type, first implement a custom PrefixType and ensure the
// Prefix() method returns the correct prefix
type UserPrefix struct{}

func (UserPrefix) Prefix() string {
	return "user"
}

// And then define your custom id type by embedding TypeID:
type UserID struct {
	typeid.TypeID[UserPrefix]
}

// Now do the same for AccountIDs
type AccountPrefix struct{}

func (AccountPrefix) Prefix() string {
	return "account"
}

type AccountID struct {
	typeid.TypeID[AccountPrefix]
}

func main() {
	// To create new IDs call typeid.New and pass your custom id type as the
	// generic argument:
	userID, _ := typeid.New[UserID]()
	accountID, _ := typeid.New[AccountID]()

	// Other than that, your custom types should have the same methods as a
	// regular TypeID.
	// For example, we can check that each ID has the correct type prefix:
	fmt.Printf("User ID prefix: %s\n", userID.Prefix())
	fmt.Printf("Account ID prefix: %s\n", accountID.Prefix())

	// Despite both of them being TypeIDs, you now get compile-time safety because
	// the compiler considers their go types to be different:
	// (typeid_test.UserID vs typeid_test.AccountID vs typeid.TypeID)
	fmt.Printf("%T != %T\n", userID, accountID)
}
Output:

User ID prefix: user
Account ID prefix: account
typeid_test.UserID != typeid_test.AccountID

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func FromSuffix added in v1.0.0

func FromSuffix[T Subtype, PT SubtypePtr[T]](suffix string) (T, error)

FromSuffix returns a new TypeID of the given suffix and type. The prefix is inferred from the Subtype.

Example:

  type UserID struct {
	   typeid.TypeID[UserPrefix]
  }
  id, err := typeid.FromSuffix[UserID]("00041061050r3gg28a1c60t3gf")
Example
tid := typeid.Must(typeid.FromSuffix[UserID]("00041061050r3gg28a1c60t3gf"))
fmt.Printf("Prefix: %s\nSuffix: %s\n", tid.Prefix(), tid.Suffix())
Output:

Prefix: user
Suffix: 00041061050r3gg28a1c60t3gf

func FromUUID

func FromUUID[T Subtype, PT SubtypePtr[T]](prefix string, uidStr string) (T, error)

FromUUID encodes the given UUID (in hex string form) as a TypeID with the given prefix.

func FromUUIDBytes

func FromUUIDBytes[T Subtype, PT SubtypePtr[T]](prefix string, bytes []byte) (T, error)

FromUUID encodes the given UUID (in byte form) as a TypeID with the given prefix.

func Must

func Must[T any](tid T, err error) T

Must returns a TypeID if the error is nil, otherwise panics. Often used with New() to create a TypeID in a single line as follows: tid := Must(New("prefix"))

func New

func New[T Subtype, PT SubtypePtr[T]]() (T, error)

New returns a new TypeID of the given type with a random suffix.

Use the generic argument to pass in your typeid Subtype:

Example:

  type UserID struct {
	   typeid.TypeID[UserPrefix]
  }
  id, err := typeid.New[UserID]()
Example
tid := typeid.Must(typeid.New[AccountID]())
fmt.Println("Prefix:", tid.Prefix())
Output:

Prefix: account

func Parse added in v1.0.0

func Parse[T Subtype, PT SubtypePtr[T]](s string) (T, error)

Parse parses a TypeID from a string of the form <prefix>_<suffix> and ensures the TypeID is of the right type.

Example:

  type UserID struct {
	   typeid.TypeID[UserPrefix]
  }
  id, err := typeid.Parse[UserID]("user_00041061050r3gg28a1c60t3gf")

Types

type AnyID added in v1.0.0

type AnyID struct {
	TypeID[AnyPrefix]
}

AnyID represents TypeIDs that accept any valid prefix.

func From

func From(prefix string, suffix string) (AnyID, error)

From returns a new TypeID with the given prefix and suffix. If suffix is the empty string, a random suffix will be generated. If you want to create an id without a prefix, pass an empty string as the prefix.

func FromString

func FromString(s string) (AnyID, error)

FromString parses a TypeID from a string of the form <prefix>_<suffix>

Example
package main

import (
	"fmt"

	_ "embed"
	"go.jetpack.io/typeid"
)

func main() {
	tid := typeid.Must(typeid.FromString("prefix_00041061050r3gg28a1c60t3gf"))
	fmt.Printf("Prefix: %s\nSuffix: %s\n", tid.Prefix(), tid.Suffix())
}
Output:

Prefix: prefix
Suffix: 00041061050r3gg28a1c60t3gf

func WithPrefix added in v1.0.0

func WithPrefix(prefix string) (AnyID, error)

WithPrefix returns a new TypeID with the given prefix and a random suffix. If you want to create an id without a prefix, pass an empty string.

Example
package main

import (
	"fmt"

	_ "embed"
	"go.jetpack.io/typeid"
)

func main() {
	tid := typeid.Must(typeid.WithPrefix("prefix"))
	fmt.Printf("New typeid: %s\n", tid)
}
Output:

Example (EmptyPrefix)
package main

import (
	"fmt"

	_ "embed"
	"go.jetpack.io/typeid"
)

func main() {
	tid := typeid.Must(typeid.WithPrefix(""))
	fmt.Printf("New typeid without prefix: %s\n", tid)
}
Output:

type AnyPrefix added in v1.0.0

type AnyPrefix struct{}

Any is a special prefix that can be used to represent TypeIDs that allow for any valid prefix.

func (AnyPrefix) Prefix added in v1.0.0

func (a AnyPrefix) Prefix() string

type PrefixType added in v1.0.0

type PrefixType interface {
	Prefix() string
}

PrefixType is the interface that defines the type if a type id. Implement your own version of this interface if you want to define a custom type: type UserPrefix struct {} func (UserPrefix) Prefix() string { return "user" }

type Subtype added in v1.0.0

type Subtype interface {
	Prefix() string
	Suffix() string
	String() string
	UUIDBytes() []byte
	UUID() string
	// contains filtered or unexported methods
}

Subtype is an interface used to create a more specific subtype of TypeID For example, if you want to create an `OrgID` type that only accepts an `org_` prefix.

type SubtypePtr added in v1.0.0

type SubtypePtr[T any] interface {
	*T
	// contains filtered or unexported methods
}

type TypeID

type TypeID[P PrefixType] struct {
	// contains filtered or unexported fields
}

TypeID is a unique identifier with a given type as defined by the TypeID spec

func (TypeID[P]) MarshalText

func (tid TypeID[P]) MarshalText() (text []byte, err error)

MarshalText implements the encoding.TextMarshaler interface. It encodes a TypeID as a string using the same logic as String()

func (TypeID[P]) Prefix added in v1.0.0

func (tid TypeID[P]) Prefix() string

Prefix returns the type prefix of the TypeID

func (*TypeID[P]) Scan added in v1.0.0

func (tid *TypeID[P]) Scan(src any) error

Scan implements the sql.Scanner interface so the TypeIDs can be read from databases transparently. Currently database types that map to string are supported.

func (TypeID[P]) String

func (tid TypeID[P]) String() string

String returns the TypeID in it's canonical string representation of the form: <prefix>_<suffix> where <suffix> is the canonical base32 representation of the UUID

func (TypeID[P]) Suffix

func (tid TypeID[P]) Suffix() string

Suffix returns the suffix of the TypeID in it's canonical base32 representation.

func (TypeID[P]) UUID

func (tid TypeID[P]) UUID() string

UUID decodes the TypeID's suffix as a UUID and returns it as a hex string

func (TypeID[P]) UUIDBytes

func (tid TypeID[P]) UUIDBytes() []byte

UUIDBytes decodes the TypeID's suffix as a UUID and returns it's bytes

func (*TypeID[P]) UnmarshalText

func (tid *TypeID[P]) UnmarshalText(text []byte) error

UnmarshalText implements the encoding.TextUnmarshaler interface. It parses a TypeID from a string using the same logic as FromString()

func (TypeID[P]) Value added in v1.0.0

func (tid TypeID[P]) Value() (driver.Value, error)

Value implements the sql.Valuer interface so that TypeIDs can be written to databases transparently. Currently, TypeIDs map to strings.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL