From e48bfc0ca0fde8950a82dcd179b37333dea50623 Mon Sep 17 00:00:00 2001
From: Spark <79936503+spa5k@users.noreply.github.com>
Date: Sat, 8 Jun 2024 10:14:53 +0530
Subject: [PATCH 1/4] feat: adding new ids

---
 .cargo/config                                 |   3 -
 .cargo/config.toml                            |   3 +
 .../workflows/build-and-test-gnu/action.yaml  | 231 +++++++++
 .github/workflows/build-rpm/action.yaml       |  93 ++++
 .github/workflows/container.yaml              |  65 +++
 .github/workflows/release.yaml                | 102 ++++
 .github/workflows/test.yaml                   |  26 +
 .vscode/settings.json                         |   7 -
 Cargo.toml                                    |  38 +-
 README.md                                     | 475 ++++++++++++++----
 docker/Dockerfile                             |  12 +-
 dprint.json                                   |  20 -
 .../base-pkg-alpine3.18-amd64.Dockerfile      |  55 ++
 infra/docker/builder-gnu.Dockerfile           |  77 +++
 ...ostgres-pg15.7-alpine3.18-amd64.Dockerfile |  45 ++
 ...ostgres-pg16.3-alpine3.18-amd64.Dockerfile |  45 ++
 justfile                                      | 267 ++++++++++
 src/cuid2.rs                                  |  36 ++
 src/ksuid.rs                                  |  23 +-
 src/lib.rs                                    |  72 +--
 src/nanoid.rs                                 |  30 +-
 src/pushid.rs                                 |  36 ++
 src/timeflake.rs                              |  49 ++
 src/typeid.rs                                 |  50 ++
 src/ulid.rs                                   |  33 +-
 src/uuid_v6.rs                                |  66 +++
 src/uuidv7.rs                                 |  74 +++
 uids.control                                  |   4 +-
 28 files changed, 1832 insertions(+), 205 deletions(-)
 delete mode 100644 .cargo/config
 create mode 100644 .cargo/config.toml
 create mode 100644 .github/workflows/build-and-test-gnu/action.yaml
 create mode 100644 .github/workflows/build-rpm/action.yaml
 create mode 100644 .github/workflows/container.yaml
 create mode 100644 .github/workflows/release.yaml
 create mode 100644 .github/workflows/test.yaml
 delete mode 100644 .vscode/settings.json
 delete mode 100644 dprint.json
 create mode 100644 infra/docker/base-pkg-alpine3.18-amd64.Dockerfile
 create mode 100644 infra/docker/builder-gnu.Dockerfile
 create mode 100644 infra/docker/uids_postgres-pg15.7-alpine3.18-amd64.Dockerfile
 create mode 100644 infra/docker/uids_postgres-pg16.3-alpine3.18-amd64.Dockerfile
 create mode 100644 justfile
 create mode 100644 src/cuid2.rs
 create mode 100644 src/pushid.rs
 create mode 100644 src/timeflake.rs
 create mode 100644 src/typeid.rs
 create mode 100644 src/uuid_v6.rs
 create mode 100644 src/uuidv7.rs

diff --git a/.cargo/config b/.cargo/config
deleted file mode 100644
index 2b25fcd..0000000
--- a/.cargo/config
+++ /dev/null
@@ -1,3 +0,0 @@
-[build]
-# Postgres symbols won't be available until runtime
-rustflags = ["-C", "link-args=-Wl,-undefined,dynamic_lookup"]
diff --git a/.cargo/config.toml b/.cargo/config.toml
new file mode 100644
index 0000000..13c456b
--- /dev/null
+++ b/.cargo/config.toml
@@ -0,0 +1,3 @@
+[target.'cfg(target_os="macos")']
+# Postgres symbols won't be available until runtime
+rustflags = ["-Clink-arg=-Wl,-undefined,dynamic_lookup"]
diff --git a/.github/workflows/build-and-test-gnu/action.yaml b/.github/workflows/build-and-test-gnu/action.yaml
new file mode 100644
index 0000000..f7eafc4
--- /dev/null
+++ b/.github/workflows/build-and-test-gnu/action.yaml
@@ -0,0 +1,231 @@
+name: build-and-test
+description: Build and test pg_idkit (meant to run inside pg_idkit/builder container)
+inputs:
+  artifact-upload:
+    type: boolean
+    default: false
+    description: |
+      Desired artifact name (will replace the natural name)
+  artifact-tarball-suffix:
+    type: string
+    default: "gnu"
+    description: |
+      Suffix that will be used on the tarball artifact (ex. '-gnu')
+  rust-container-version:
+    type: string
+    default: 1.76
+    description: |
+      Version of rust to use in the container
+  apt-cache-dir:
+    type: string
+    default: /var/cache/apt
+  cargo-home-dir:
+    type: string
+    default: /usr/local/cargo
+  cargo-target-dir:
+    type: string
+    default: /usr/local/build/target
+  sccache-dir:
+    type: string
+    default: /usr/local/sccache
+  cargo-build-rustc-wrapper:
+    type: string
+    default: /usr/local/cargo/bin/sccache
+  cargo-env-incremental:
+    type: string
+    default: "0"
+  cargo-env-profile:
+    type: string
+    default: ci
+  user:
+    type: string
+    default: idkit
+  pgrx-pg-version:
+    type: string
+    default: pg16
+    decription: |
+      PGRX version (ex. 'pg15', 'pg16')
+  pg-version:
+    type: string
+    default: 16.2
+    decription: |
+      Postgres version (ex. '15.6, '16.2')
+outputs: {}
+runs:
+  using: "composite"
+  steps:
+    # Checkout the repo
+    - uses: actions/checkout@v3
+
+    #########
+    # Cache #
+    #########
+
+    - name: Cache CARGO_HOME
+      uses: actions/cache@v3
+      continue-on-error: false
+      with:
+        path: |
+          ${{ inputs.cargo-home-dir }}
+        key: pg_idkit-tests-rust-${{ inputs.rust-container-version }}-cargo-${{ runner.os }}
+
+    - name: Cache apt install
+      uses: actions/cache@v3
+      continue-on-error: false
+      with:
+        path: |
+          ${{ inputs.apt-cache-dir }}
+        key: pg_idkit-tests-apt-cache-${{ inputs.rust-container-version }}-cargo-${{ runner.os }}
+
+    - name: Cache sccache
+      uses: actions/cache@v3
+      continue-on-error: false
+      with:
+        path: |
+          ${{ inputs.sccache-dir }}
+        key: pg_idkit-tests-sccache-${{ inputs.rust-container-version }}-cargo-${{ runner.os }}
+
+    - name: Cache pgrx init
+      uses: actions/cache@v3
+      continue-on-error: false
+      with:
+        path: |
+          /home/${{ inputs.user }}/.pgrx
+        key: pg_idkit-tests-pgrx-init-${{ inputs.rust-container-version }}-cargo-${{ runner.os }}
+
+    #########
+    # Setup #
+    #########
+
+    - name: Add idkit to group
+      shell: bash
+      run: |
+        chgrp -R idkit $HOME &&
+        chgrp -R idkit /__w/pg_idkit &&
+        chmod g+w -R /__w/pg_idkit
+
+    # Add directory used by worker as safe dir for git
+    - name: Add git safe dir
+      shell: bash
+      run: |
+        git config --global --add safe.directory /__w/pg_idkit/pg_idkit
+        su idkit -c "git config --global --add safe.directory /__w/pg_idkit/pg_idkit"
+
+
+    - name: Reinstall deps due to GLIBC issue
+      if: ${{ inputs.artifact-upload }}
+      shell: bash
+      env:
+        CARGO_BUILD_RUSTC_WRAPPER: ${{ inputs.cargo-build-rustc-wrapper }}
+        CARGO_HOME: ${{ inputs.cargo-home-dir }}
+        CARGO_INCREMENTAL: ${{ inputs.cargo-env-incrmental }}
+        CARGO_PROFILE: ${{ inputs.cargo-profile }}
+        CARGO_TARGET_DIR: ${{ inputs.cargo-target-dir }}
+        PGRX_PG_VERSION: ${{ inputs.pgrx-pg-version }}
+        PGRX_PKG_PATH_PREFIX: ${{ inputs.cargo-target-dir }}
+        PKG_PG_VERSION: ${{ inputs.pg-version }}
+        SCCACHE_DIR: ${{ inputs.sccache-dir }}
+        DOCKER_BUILD_USER: ${{ inputs.user }}
+      run: |
+        su idkit -c "cargo install --locked --force cargo-get cargo-edit"
+
+    ###############
+    # Build/Tests #
+    ###############
+
+    # Initialize cargo-pgrx if necessary
+    - name: Initialize cargo-pgrx
+      shell: bash
+      env:
+        CARGO_BUILD_RUSTC_WRAPPER: ${{ inputs.cargo-build-rustc-wrapper }}
+        CARGO_HOME: ${{ inputs.cargo-home-dir }}
+        CARGO_INCREMENTAL: ${{ inputs.cargo-env-incrmental }}
+        CARGO_PROFILE: ${{ inputs.cargo-profile }}
+        CARGO_TARGET_DIR: ${{ inputs.cargo-target-dir }}
+        PGRX_PG_VERSION: ${{ inputs.pgrx-pg-version }}
+        PGRX_PKG_PATH_PREFIX: ${{ inputs.cargo-target-dir }}
+        PKG_PG_VERSION: ${{ inputs.pg-version }}
+        SCCACHE_DIR: ${{ inputs.sccache-dir }}
+        DOCKER_BUILD_USER: ${{ inputs.user }}
+      run: |
+        su idkit -c "just pgrx-init"
+
+    # Run cargo check
+    - name: Run cargo check
+      shell: bash
+      env:
+        CARGO_BUILD_RUSTC_WRAPPER: ${{ inputs.cargo-build-rustc-wrapper }}
+        CARGO_HOME: ${{ inputs.cargo-home-dir }}
+        CARGO_INCREMENTAL: ${{ inputs.cargo-env-incrmental }}
+        CARGO_PROFILE: ${{ inputs.cargo-profile }}
+        CARGO_TARGET_DIR: ${{ inputs.cargo-target-dir }}
+        PGRX_PG_VERSION: ${{ inputs.pgrx-pg-version }}
+        PGRX_PKG_PATH_PREFIX: ${{ inputs.cargo-target-dir }}
+        PKG_PG_VERSION: ${{ inputs.pg-version }}
+        SCCACHE_DIR: ${{ inputs.sccache-dir }}
+        DOCKER_BUILD_USER: ${{ inputs.user }}
+      run: |
+        su idkit -c "cargo check"
+
+    # Run cargo build
+    - name: Run cargo test
+      shell: bash
+      env:
+        CARGO_BUILD_RUSTC_WRAPPER: ${{ inputs.cargo-build-rustc-wrapper }}
+        CARGO_HOME: ${{ inputs.cargo-home-dir }}
+        CARGO_INCREMENTAL: ${{ inputs.cargo-env-incrmental }}
+        CARGO_PROFILE: ${{ inputs.cargo-profile }}
+        CARGO_TARGET_DIR: ${{ inputs.cargo-target-dir }}
+        PGRX_PG_VERSION: ${{ inputs.pgrx-pg-version }}
+        PGRX_PKG_PATH_PREFIX: ${{ inputs.cargo-target-dir }}
+        PKG_PG_VERSION: ${{ inputs.pg-version }}
+        SCCACHE_DIR: ${{ inputs.sccache-dir }}
+        DOCKER_BUILD_USER: ${{ inputs.user }}
+      run: |
+        su idkit -c "cargo build"
+
+    # Run cargo test
+    - name: Run cargo test
+      shell: bash
+      env:
+        CARGO_BUILD_RUSTC_WRAPPER: ${{ inputs.cargo-build-rustc-wrapper }}
+        CARGO_HOME: ${{ inputs.cargo-home-dir }}
+        CARGO_INCREMENTAL: ${{ inputs.cargo-env-incrmental }}
+        CARGO_PROFILE: ${{ inputs.cargo-profile }}
+        CARGO_TARGET_DIR: ${{ inputs.cargo-target-dir }}
+        PGRX_PG_VERSION: ${{ inputs.pgrx-pg-version }}
+        PKG_PG_VERSION: ${{ inputs.pg-version }}
+        SCCACHE_DIR: ${{ inputs.sccache-dir }}
+        DOCKER_BUILD_USER: ${{ inputs.user }}
+      run: |
+        su idkit -c "cargo test"
+
+    #############
+    # Artifacts #
+    #############
+
+    # Run cargo test
+    - name: Build a package
+      if: ${{ inputs.artifact-upload }}
+      shell: bash
+      env:
+        CARGO_BUILD_RUSTC_WRAPPER: ${{ inputs.cargo-build-rustc-wrapper }}
+        CARGO_HOME: ${{ inputs.cargo-home-dir }}
+        CARGO_INCREMENTAL: ${{ inputs.cargo-env-incrmental }}
+        CARGO_PROFILE: ${{ inputs.cargo-profile }}
+        CARGO_TARGET_DIR: ${{ inputs.cargo-target-dir }}
+        PGRX_PG_VERSION: ${{ inputs.pgrx-pg-version }}
+        PGRX_PKG_PATH_PREFIX: ${{ inputs.cargo-target-dir }}
+        PKG_PG_VERSION: ${{ inputs.pg-version }}
+        PKG_TARBALL_SUFFIX: ${{ inputs.artifact-tarball-suffix }}
+        SCCACHE_DIR: ${{ inputs.sccache-dir }}
+        DOCKER_BUILD_USER: ${{ inputs.user }}
+      run: |
+        su idkit -c "just package"
+
+    # Upload artifact
+    - name: Upload artifact
+      if: ${{ inputs.artifact-upload }}
+      uses: actions/upload-artifact@v3
+      with:
+        path: pg_idkit-*.tar.gz
\ No newline at end of file
diff --git a/.github/workflows/build-rpm/action.yaml b/.github/workflows/build-rpm/action.yaml
new file mode 100644
index 0000000..8e46d77
--- /dev/null
+++ b/.github/workflows/build-rpm/action.yaml
@@ -0,0 +1,93 @@
+name: build-rpm
+description: Build an RPM for pg_idkit
+inputs:
+  artifact-upload:
+    type: boolean
+    description: |
+      Whether to upload an artifact or not
+  artifact-name:
+    type: string
+    description: |
+      Desired artifact name (will replace the natural name)
+  gh-runner:
+    type: string
+    default: ubuntu-latest
+    decription: |
+      GitHub runner to use
+  rpm-arch:
+    type: string
+    default: x86_64
+    decription: |
+      Architecture to use while building the RPM
+  pgrx-pg-version:
+    type: string
+    default: pg16
+    decription: |
+      PGRX version (ex. 'pg15', 'pg16')
+  pg-version:
+    type: string
+    default: 16.2
+    decription: |
+      Postgres version (ex. '15.6, '16.2')
+  cargo-pgrx-version:
+    type: string
+    default: 0.11.3
+    decription: |
+      cargo-pgrx version (ex. '0.11.3')
+  user:
+    type: string
+    default: runner
+outputs: {}
+runs:
+  using: "composite"
+  steps:
+    - uses: actions/checkout@v3
+
+    - uses: Swatinem/rust-cache@v2
+
+    - name: Cache default PGRX_HOME
+      uses: actions/cache@v3
+      continue-on-error: false
+      with:
+        path: |
+          /home/runner/.pgrx
+        key: pg_idkit-pkg-rpm-pgrx-${{ inputs.rpm-arch }}-${{ inputs.gh-runner }}
+
+    - name: Install Rust deps
+      uses: taiki-e/install-action@v2
+      with:
+        tool: cargo-get,just,cargo-generate-rpm,cargo-pgrx@${{ inputs.cargo-pgrx-version }}
+
+    - name: Initialize cargo-pgrx
+      shell: bash
+      env:
+        PGRX_PG_VERSION: ${{ inputs.pgrx-pg-version }}
+        PKG_PG_VERSION: ${{ inputs.pg-version }}
+      run: |
+        [[ -d /home/runner/.pgrx ]] || cargo pgrx init
+
+    - name: Build RPM
+      shell: bash
+      env:
+        DOCKER_BUILD_USER: ${{ inputs.user }}
+        PGRX_PG_VERSION: ${{ inputs.pgrx-pg-version }}
+        PKG_PG_VERSION: ${{ inputs.pg-version }}
+      run: just package build-rpm
+
+    - name: Get RPM output path
+      id: rpm-output
+      shell: bash
+      env:
+        DOCKER_BUILD_USER: ${{ inputs.user }}
+        PGRX_PG_VERSION: ${{ inputs.pgrx-pg-version }}
+        PKG_PG_VERSION: ${{ inputs.pg-version }}
+      run: |
+        echo path=$(just print-rpm-output-path) >> $GITHUB_OUTPUT
+        echo filename=$(just print-rpm-output-file-name) >> $GITHUB_OUTPUT
+
+    - name: Upload artifact
+      if: ${{ inputs.artifact-upload }}
+      uses: actions/upload-artifact@v3
+      with:
+        name: ${{ steps.rpm-output.outputs.filename }}
+        path: ${{ steps.rpm-output.outputs.path }}
\ No newline at end of file
diff --git a/.github/workflows/container.yaml b/.github/workflows/container.yaml
new file mode 100644
index 0000000..b38b676
--- /dev/null
+++ b/.github/workflows/container.yaml
@@ -0,0 +1,65 @@
+name: container
+
+on:
+  push:
+    branches:
+      # Run on auto-generated release PRs
+      - prep-release-v[0-9]+\.[0-9]+\.[0-9]+
+    tags:
+      - v[0-9]+\.[0-9]+\.[0-9]+
+
+jobs:
+  build:
+    permissions:
+      contents: read
+      packages: write
+    runs-on: ${{ matrix.config.gh.runner }}
+    strategy:
+      matrix:
+        config:
+          - triple: x86_64-unknown-linux-musl
+            gh:
+              runner: ubuntu-22.04
+            container:
+              arch: amd64
+              pg_version: 15.6
+              os_version: alpine3.18
+          - triple: x86_64-unknown-linux-musl
+            gh:
+              runner: ubuntu-22.04
+            container:
+              arch: amd64
+              pg_version: 16.2
+              os_version: alpine3.18
+    steps:
+      - uses: actions/checkout@v3
+      - uses: docker/setup-qemu-action@v3
+      - uses: taiki-e/install-action@v2
+        with:
+          tool: cargo-get,just
+
+      - name: Registry login
+        uses: docker/login-action@v3
+        with:
+          registry: ghcr.io
+          username: ${{ github.actor }}
+          password: ${{ secrets.GITHUB_TOKEN }}
+
+      - name: Build container image (prerelease)
+        if: ${{ startsWith(github.ref, 'refs/heads/prep-release') }}
+        run: just build-image push-image
+        env:
+          CONTAINER_IMAGE_ARCH: ${{ matrix.config.container.arch }}
+          PGRX_PG_VERSION: ${{ matrix.config.container.pg_version }}
+          POSTGRES_IMAGE_VERSION: ${{ matrix.config.container.pg_version }}
+          POSTGRES_OS_IMAGE_VERSION: ${{ matrix.config.container.os_version }}
+          PGIDKIT_IMAGE_TAG_SUFFIX: "-prerelease"
+
+      - name: Build container image
+        if: ${{ startsWith(github.ref, 'refs/tags/v') }}
+        run: just build-image push-image
+        env:
+          CONTAINER_IMAGE_ARCH: ${{ matrix.config.container.arch }}
+          PGRX_PG_VERSION: ${{ matrix.config.container.pg_version }}
+          POSTGRES_IMAGE_VERSION: ${{ matrix.config.container.pg_version }}
+          POSTGRES_OS_IMAGE_VERSION: ${{ matrix.config.container.os_version }}
\ No newline at end of file
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
new file mode 100644
index 0000000..689f1ba
--- /dev/null
+++ b/.github/workflows/release.yaml
@@ -0,0 +1,102 @@
+name: release
+
+on:
+  workflow_dispatch:
+    inputs:
+      version:
+        description: Version to release (ex. `0.1.0`)
+        required: false
+        type: string
+
+  push:
+    branches:
+      # Run on all commits to main, because GitHub somehow doesn't support only specifying tag patterns
+      # (filtering must be done at the per-job level with an `if`)
+      - main
+      # Run on auto-generated release PRs
+      - prep-release-v[0-9]+\.[0-9]+\.[0-9]+
+    tags:
+      # Run on released tags (created by automated post-merge release-tagging), to generate the actual release
+      - v[0-9]+\.[0-9]+\.[0-9]+
+
+jobs:
+  build-rpm:
+    runs-on: ubuntu-latest
+    if: ${{ startsWith(github.ref, 'refs/tags/v') || startsWith(github.ref, 'refs/tags/prep-release-v')  }}
+    strategy:
+      matrix:
+        config:
+          - pgrx:
+              pg-version: pg15
+            pg:
+              version: 15.6
+          - pgrx:
+              pg-version: pg16
+            pg:
+              version: 16.2
+    steps:
+      - uses: actions/checkout@v3
+
+      - name: Build the RPM (reuse workflow)
+        uses: ./.github/workflows/build-rpm
+        with:
+          artifact-upload: true
+          pgrx-pg-version: ${{ matrix.config.pgrx.pg-version }}
+          pg-version: ${{ matrix.config.pg.version }}
+
+  build-zip-gnu:
+    runs-on: ubuntu-latest
+    if: ${{ startsWith(github.ref, 'refs/tags/v') || startsWith(github.ref, 'refs/tags/prep-release-v')  }}
+    container:
+      image: ghcr.io/spa5k/uids-postgres/builder-gnu:0.1.x
+    strategy:
+      matrix:
+        config:
+          - pgrx:
+              pg-version: pg15
+            pg:
+              version: 15.6
+          - pgrx:
+              pg-version: pg16
+            pg:
+              version: 16.2
+    steps:
+      - uses: actions/checkout@v3
+
+      - name: Build the package (reuse workflow)
+        uses: ./.github/workflows/build-and-test-gnu
+        with:
+          artifact-upload: true
+          artifact-tarball-suffix: "-${{ matrix.config.pgrx.pg-version }}-gnu"
+          pgrx-pg-version: ${{ matrix.config.pgrx.pg-version }}
+          pg-version: ${{ matrix.config.pg.version }}
+
+  release:
+    runs-on: ubuntu-latest
+    if: ${{ startsWith(github.ref, 'refs/tags/v') || startsWith(github.ref, 'refs/tags/prep-release-v')  }}
+    permissions:
+      contents: write
+    needs:
+      - build-rpm
+      - build-zip-gnu
+    steps:
+      # Checkout the repository
+      - uses: actions/checkout@v3
+
+      # Download all artifacts
+      - uses: actions/download-artifact@v3
+        with:
+          path: artifacts
+
+      # Create release (pre-release if we're prepping)
+      - name: Create release
+        uses: softprops/action-gh-release@v1
+        with:
+          prerelease: ${{ startsWith(github.ref, 'refs/heads/prep-release') }}
+          draft: ${{ startsWith(github.ref, 'refs/heads/prep-release') }}
+          tag_name: ${{ github.ref || inputs.version }}
+          # NOTE: while we have the CHANGELOG file, it always contains *all* changes,
+          # so we will use the generated GitHub commits for now
+          generate_release_notes: true
+          files: |
+            ./artifacts/*/*
\ No newline at end of file
diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml
new file mode 100644
index 0000000..c5d2249
--- /dev/null
+++ b/.github/workflows/test.yaml
@@ -0,0 +1,26 @@
+name: test
+
+on:
+  push:
+
+jobs:
+  test:
+    runs-on: ubuntu-latest
+    container:
+      image: ghcr.io/spa5k/uids-postgres/builder-gnu:0.1.x
+    strategy:
+      matrix:
+        config:
+        - rpm:
+            arch: x86_64
+          pgrx:
+            version: pg15
+        - rpm:
+            arch: x86_64
+          pgrx:
+            version: pg16
+    steps:
+      - uses: actions/checkout@v3
+
+      - name: Build & test the project
+        uses: ./.github/workflows/build-and-test-gnu
\ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
deleted file mode 100644
index 1ff8bf7..0000000
--- a/.vscode/settings.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
-  "conventionalCommits.scopes": [
-    "main",
-    "readme",
-    "nanoid"
-  ]
-}
diff --git a/Cargo.toml b/Cargo.toml
index fa645de..e4b7f82 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,33 +1,45 @@
 [package]
 name = "uids"
-version = "0.2.0"
+version = "0.0.0"
 edition = "2021"
-description = "PostgreSQL Extension to generate various type of Unique IDS."
 
 [lib]
 crate-type = ["cdylib"]
 
 [features]
-default = ["pg13"]
-pg10 = ["pgx/pg10", "pgx-tests/pg10"]
-pg11 = ["pgx/pg11", "pgx-tests/pg11"]
-pg12 = ["pgx/pg12", "pgx-tests/pg12"]
-pg13 = ["pgx/pg13", "pgx-tests/pg13"]
-pg14 = ["pgx/pg14", "pgx-tests/pg14"]
+default = ["pg16"]
+pg11 = ["pgrx/pg11", "pgrx-tests/pg11"]
+pg12 = ["pgrx/pg12", "pgrx-tests/pg12"]
+pg13 = ["pgrx/pg13", "pgrx-tests/pg13"]
+pg14 = ["pgrx/pg14", "pgrx-tests/pg14"]
+pg15 = ["pgrx/pg15", "pgrx-tests/pg15"]
+pg16 = ["pgrx/pg16", "pgrx-tests/pg16"]
 pg_test = []
 
 [dependencies]
 nanoid = "0.4.0"
-pgx = "0.4.5"
-rusty_ulid = "1.0.0"
-svix-ksuid = "0.6.0"
+pgrx = "=0.11.4"
+rusty_ulid = "2.0.0"
+svix-ksuid = "0.8.0"
+type-safe-id = "0.3.0"
+uuid = { version = "1.8.0", features = [
+    "v7",
+    "v4",
+    "v6",
+    "v8",
+    "fast-rng",
+    "macro-diagnostics",
+] }
+getrandom = "0.2"
+cuid2 = "0.1.2"
+timeflake-rs = "0.3.0"
+pushid = "0.0.1"
 
 [dev-dependencies]
-pgx-tests = "0.4.5"
+pgrx-tests = "=0.11.4"
 
 [profile.dev]
 panic = "unwind"
-lto = "thin"
 
 [profile.release]
 panic = "unwind"
diff --git a/README.md b/README.md
index 7608897..2e9c1fe 100644
--- a/README.md
+++ b/README.md
@@ -1,152 +1,449 @@
-# PostgreSQL Extension to generate various type of Unique IDS.
+Here's the updated README with the corrected links in the table:
 
-## 1. Supported IDs
+# PostgreSQL Extension for Generating Unique IDs
 
-1. [NanoId](https://github.com/ai/nanoid)
+<h1 align="center">
+  uids
+</h1>
 
-2. [Ksuid](https://github.com/segmentio/ksuid)
+```sql
+postgres=# CREATE EXTENSION uids;
+CREATE EXTENSION
 
+postgres=# SELECT generate_typeid('user');
+ generate_typeid
+--------------------------------------
+ user_01h2xcejqtf2nbrexx3vqjhp41
+```
+
+## Description
+
+| Methodology               | Function                                    | Crate                                | Description                                              |
+|---------------------------|---------------------------------------------|--------------------------------------|----------------------------------------------------------|
+| [UUID v6][uuidv6]         | `generate_uuidv6()`                         | [`uuid`][crate-uuid]                 | UUID v6 ([RFC 4122][rfc-4122-update])                    |
+|                           | `generate_uuidv6_text()`                    |                                      | UUID v6 as text                                          |
+|                           | `generate_uuidv6_uuid()`                    |                                      | UUID v6 as Postgres UUID object                          |
+| [UUID v7][uuidv7]         | `generate_uuidv7()`                         | [`uuid`][crate-uuid]                 | UUID v7 ([RFC 4122][rfc-4122-update])                    |
+|                           | `generate_uuidv7_bytes()`                   |                                      | UUID v7 as bytes                                         |
+|                           | `generate_uuidv7_from_string(TEXT)`         |                                      | Generate UUID v7 from a string                           |
+|                           | `parse_uuidv7(TEXT)`                        |                                      | Parse UUID v7                                            |
+| [NanoId][nanoid]          | `generate_nanoid()`                         | [`nanoid`][crate-nanoid]             | NanoID, developed by [Andrey Sitnik][github-ai]          |
+|                           | `generate_nanoid_length(INT)`               |                                      | NanoID with a custom length                              |
+|                           | `generate_nanoid_c(TEXT)`                   |                                      | NanoID with custom alphabets                             |
+|                           | `generate_nanoid_length_c(INT, TEXT)`       |                                      | NanoID with custom length and alphabets                  |
+| [Ksuid][ksuid]            | `generate_ksuid()`                          | [`svix-ksuid`][crate-svix-ksuid]     | Created by [Segment][segment]                            |
+|                           | `generate_ksuid_bytes()`                    |                                      | KSUID as bytes                                           |
+| [Ulid][ulid]              | `generate_ulid()`                           | [`ulid`][crate-ulid]                 | Unique, lexicographically sortable identifiers           |
+|                           | `generate_ulid_bytes()`                     |                                      | ULID as bytes                                            |
+|                           | `generate_ulid_from_string(TEXT)`           |                                      | Generate ULID from a string                              |
+| [Timeflake][timeflake]    | `generate_timeflake()`                      | [`timeflake-rs`][crate-timeflake-rs] | Twitter's Snowflake + Instagram's ID + Firebase's PushID |
+|                           | `generate_timeflake_bytes()`                |                                      | Timeflake as bytes                                       |
+|                           | `generate_timeflake_uuid()`                 |                                      | Timeflake as UUID                                        |
+| [PushId][pushid]          | `generate_pushid()`                         | [`pushid`][crate-pushid]             | Google Firebase's PushID                                 |
+|                           | `generate_pushid_text()`                    |                                      | PushID as text                                           |
+| [Cuid2][cuid2]            | `generate_cuid2()`                          | [`cuid2`][crate-cuid2]               | CUID2                                                    |
+|                           | `check_cuid2(TEXT)`                         |                                      | Check if a string is a valid CUID2                       |
+| [TypeId][typeid]          | `generate_typeid(TEXT)`                     | [`typeid`][crate-typeid]             | Generate TypeId with a specific prefix                   |
+|                           | `check_typeid(TEXT, TEXT)`                  |                                      | Check if a TypeId matches a specific prefix              |
+
+This Postgres extension is made possible thanks to [`pgrx`][pgrx].
+
+## Supported IDs
+
+1. [NanoId](https://github.com/ai/nanoid)
+2. [Ksuid](https://github.com/segmentio/ksuid)
 3. [Ulid](https://github.com/ulid/spec)
+4. [TypeId](https://github.com/jetpack-io/typeid)
+5. [UUIDv7](https://github.com/uuid-rs/uuid)
+6. [Cuid2](https://github.com/paralleldrive/cuid2)
+7. [PushId](https://github.com/firebase/firebase-js-sdk)
+8. [Timeflake](https://github.com/anthonynsimon/timeflake)
+9. [UUIDv6](https://github.com/uuid-rs/uuid)
 
-## 2. Installation
+[crate-uuid]: https://crates.io/crates/uuid
+[crate-nanoid]: https://crates.io/crates/nanoid
+[crate-svix-ksuid]: https://crates.io/crates/svix-ksuid
+[crate-ulid]: https://crates.io/crates/ulid
+[crate-timeflake-rs]: https://crates.io/crates/timeflake-rs
+[crate-pushid]: https://crates.io/crates/pushid
+[crate-cuid2]: https://crates.io/crates/cuid2
+[crate-typeid]: https://crates.io/crates/typeid
+[postgres]: https://www.postgresql.org/
+[uuidv6]: https://github.com/uuid-rs/uuid
+[uuidv7]: https://github.com/uuid-rs/uuid
+[nanoid]: https://github.com/ai/nanoid
+[ksuid]: https://github.com/segmentio/ksuid
+[ulid]: https://github.com/ulid/spec
+[timeflake]: https://github.com/anthonynsimon/timeflake
+[pushid]: https://github.com/firebase/firebase-js-sdk
+[cuid2]: https://github.com/paralleldrive/cuid2
+[typeid]: https://github.com/jetpack-io/typeid
+[pgrx]: https://github.com/zombodb/pgx
 
-### 2.1. Installation on non docker environment
 
-2.1.1. Install rust through rustup.
 
-```bash
-curl https://sh.rustup.rs -sSf | sh
-```
+## Installation
 
-2.1.2. Prepare your postgres installation
-2.1.3. Install pgx
+### Non-Docker Environment
 
-```bash
-cargo install cargo-pgx
-```
+1. **Install Rust via rustup:**
 
-2.1.4. Initialize pgx for the postgres version you have already installed
+    ```bash
+    curl https://sh.rustup.rs -sSf | sh
+    ```
 
-Handle the number accordingly.
+2. **Prepare your PostgreSQL installation.**
 
-```bash
-cargo pgx init --pg14 $(which pg_config)
-```
+3. **Install pgx:**
 
-2.1.5. Install the extension
+    ```bash
+    cargo install cargo-pgx
+    ```
 
-```bash
-git clone https://github.com/spa5k/uids-postgres \
-&& cd uids-postgres \
-&& cargo pgx install
-```
+4. **Initialize pgx for your PostgreSQL version:**
+
+    ```bash
+    cargo pgx init --pg14 $(which pg_config)
+    ```
+
+5. **Clone the repository and install the extension:**
 
-### 2.2 Installation on docker environment
+    ```bash
+    git clone https://github.com/spa5k/uids-postgres
+    cd uids-postgres
+    cargo pgx install
+    ```
 
-Check the included [Dockerfile](./docker/Dockerfile) for the installation template.
+### Docker Environment
 
-## 3. Functions available
+Refer to the included [Dockerfile](./docker/Dockerfile) for the installation template.
 
-### 3.0. Enable the extension
+## Usage
+
+### Enable the Extension
 
 ```sql
 CREATE EXTENSION IF NOT EXISTS uids;
 ```
 
-### 3.1. KSUID -
+### Functions
 
-1. Generate a new KSUID
+#### KSUID
 
-```sql
-select generate_ksuid();
+1. **Generate a new KSUID:**
 
------------------------------
+    ```sql
+    SELECT generate_ksuid();
+    ```
 
-28KKKI8lpDkK2lHbAdWdgJYoLWF
-```
+    Example output:
 
-2. Generate a KSUID bytes.
+    ```
+    28KKKI8lpDkK2lHbAdWdgJYoLWF
+    ```
 
-```sql
-select generate_ksuid_bytes();
+2. **Generate KSUID bytes:**
 
------------------------------
+    ```sql
+    SELECT generate_ksuid_bytes();
+    ```
 
-\x0ef557bc9b5b8027f222e2b32ed65e91b6bb8eb6
-```
+    Example output:
 
-### 3.2. NanoId -
+    ```
+    \x0ef557bc9b5b8027f222e2b32ed65e91b6bb8eb6
+    ```
 
-1. Generate a new NanoId with default size of 21
+#### NanoId
 
-```sql
-select generate_nanoid();
+1. **Generate a new NanoId (default size 21):**
 
------------------------------
+    ```sql
+    SELECT generate_nanoid();
+    ```
 
-FfuwjZHjS5j5rATHVyl8M
-```
+    Example output:
 
-2. Generate a NanoId with a custom size
+    ```
+    FfuwjZHjS5j5rATHVyl8M
+    ```
 
-```sql
-select generate_nanoid_length(10);
+2. **Generate a NanoId with a custom size:**
 
------------------------------
+    ```sql
+    SELECT generate_nanoid_length(10);
+    ```
 
-V2D2D7-dnw
-```
+    Example output:
 
-3. Generate a NanoId with a custom alphabets with length of 21
+    ```
+    V2D2D7-dnw
+    ```
 
-```sql
--- Length of the nanoid is first argument, while the alphabets one is second.
-select generate_nanoid_c('1234567890abcdef');
+3. **Generate a NanoId with custom alphabets (length 21):**
 
------------------------------
+    ```sql
+    SELECT generate_nanoid_c('1234567890abcdef');
+    ```
 
-6df80ad84587f4a20838c
-```
+    Example output:
 
-4. Generate a NanoId with a custom alphabets and custom length
+    ```
+    6df80ad84587f4a20838c
+    ```
 
-```sql
--- Length of the nanoid is first argument, while the alphabets one is second.
-select generate_nanoid_length_c(10, '1234567890abcdef');
+4. **Generate a NanoId with custom alphabets and custom length:**
 
------------------------------
+    ```sql
+    SELECT generate_nanoid_length_c(10, '1234567890abcdef');
+    ```
 
-050487bff0
-```
+    Example output:
 
-### 3.3. Ulid -
+    ```
+    050487bff0
+    ```
 
-1. Generate a new Ulid
+#### Ulid
 
-```sql
-select generate_ulid();
+1. **Generate a new Ulid:**
 
------------------------------
+    ```sql
+    SELECT generate_ulid();
+    ```
 
-01G1JE4GXWC1A9PXHG0SXQDE1J
-```
+    Example output:
 
-2. Generate Ulid bytes
+    ```
+    01G1JE4GXWC1A9PXHG0SXQDE1J
+    ```
 
-```sql
-select generate_ulid_bytes();
+2. **Generate Ulid bytes:**
 
------------------------------
+    ```sql
+    SELECT generate_ulid_bytes();
+    ```
 
-\x018064e2bff9e6bb876aa8948e50d9c6
-```
+    Example output:
 
-3. Generate Ulid from a custom string
+    ```
+    \x018064e2bff9e6bb876aa8948e50d9c6
+    ```
 
-```sql
-select generate_ulid_from_string('01CAT3X5Y5G9A62F1rFA6Tnice');
+3. **Generate Ulid from a custom string:**
 
------------------------------
+    ```sql
+    SELECT generate_ulid_from_string('01CAT3X5Y5G9A62F1rFA6Tnice');
+    ```
 
-01CAT3X5Y5G9A62F1RFA6TN1CE
-```
+    Example output:
+
+    ```
+    01CAT3X5Y5G9A62F1RFA6TN1CE
+    ```
+
+#### TypeId
+
+1. **Generate a TypeId with a specific prefix:**
+
+    ```sql
+    SELECT generate_typeid('user');
+    ```
+
+    Example output:
+
+    ```
+    user_01h2xcejqtf2nbrexx3vqjhp41
+    ```
+
+2. **Check if a TypeId matches a specific prefix:**
+
+    ```sql
+    SELECT check_typeid('user', 'user_01h2xcejqtf2nbrexx3vqjhp41');
+    ```
+
+    Example output:
+
+    ```
+    true
+    ```
+
+#### UUIDv7
+
+1. **Generate a new UUIDv7:**
+
+    ```sql
+    SELECT generate_uuidv7();
+    ```
+
+    Example output:
+
+    ```
+    01809424-3e59-7c05-9219-566f82fff672
+    ```
+
+2. **Generate UUIDv7 bytes:**
+
+    ```sql
+    SELECT generate_uuidv7_bytes();
+    ```
+
+    Example output:
+
+    ```
+    \x018094243e597c059219566f82fff672
+    ```
+
+3. **Generate UUIDv7 from a string:**
+
+    ```sql
+    SELECT generate_uuidv7_from_string('67e55044-10b1-426f-9247-bb680e5fe0c8');
+    ```
+
+    Example output:
+
+    ```
+    67e55044-10b1-426f-9247-bb680e5fe0c8
+    ```
+
+4. **Parse UUIDv7:**
+
+    ```sql
+    SELECT parse_uuidv7('67e55044-10b1-426f-9247-bb680e5fe0c8');
+    ```
+
+    Example output:
+
+    ```
+    67e55044-10b1-426f-9247-bb680e5fe0c8
+    ```
+
+#### Cuid2
+
+1. **Generate a new Cuid2:**
+
+    ```sql
+    SELECT generate_cuid2();
+    ```
+
+    Example output:
+
+    ```
+    cl8f8y8f80000000000000000
+    ```
+
+2. **Check if a string is a valid Cuid2:**
+
+    ```sql
+    SELECT check_cuid2('cl8f8y8f80000000000000000');
+    ```
+
+    Example output:
+
+    ```
+    true
+    ```
+
+#### PushId
+
+1. **Generate a new PushId:**
+
+    ```sql
+    SELECT generate_pushid();
+    ```
+
+    Example output:
+
+    ```
+    -MZ1e2f3g4h5i6j7k8l9
+    ```
+
+2. **Generate a PushId as text:**
+
+    ```sql
+    SELECT generate_pushid_text();
+    ```
+
+    Example output:
+
+    ```
+    -MZ1e2f3g4h5i6j7k8l9
+    ```
+
+#### Timeflake
+
+1. **Generate a new Timeflake:**
+
+    ```sql
+    SELECT generate_timeflake();
+    ```
+
+    Example output:
+
+    ```
+    01F8MECHJ8KZ9Q9J8KZ9Q9J8KZ
+    ```
+
+2. **Generate Timeflake bytes:**
+
+    ```sql
+    SELECT generate_timeflake_bytes();
+    ```
+
+    Example output:
+
+    ```
+    \x018064e2bff9e6bb876aa8948e50d9c6
+    ```
+
+3. **Generate Timeflake UUID:**
+
+    ```sql
+    SELECT generate_timeflake_uuid();
+    ```
+
+    Example output:
+
+    ```
+    018064e2-bff9-e6bb-876a-a8948e50d9c6
+    ```
+
+#### UUIDv6
+
+1. **Generate a new UUIDv6:**
+
+    ```sql
+    SELECT generate_uuidv6();
+    ```
+
+    Example output:
+
+    ```
+    1e4eaa4e-7c4b-6e5d-8a4e-7c4b6e5d8a4e
+    ```
+
+2. **Generate a UUIDv6 as text:**
+
+    ```sql
+    SELECT generate_uuidv6_text();
+    ```
+
+    Example output:
+
+    ```
+    1e4eaa4e-7c4b-6e5d-8a4e-7c4b6e5d8a4e
+    ```
+
+3. **Generate a UUIDv6 as a Postgres UUID object:**
+
+    ```sql
+    SELECT generate_uuidv6_uuid();
+    ```
+
+    Example output:
+
+    ```
+    1e4eaa4e-7c4b-6e5d-8a4e-7c4b6e5d8a4e
+    ```
+
+This setup provides a comprehensive set of functions to generate and validate various types of unique identifiers within a PostgreSQL extension using `pgx`.
diff --git a/docker/Dockerfile b/docker/Dockerfile
index b8fd3d6..64dea04 100644
--- a/docker/Dockerfile
+++ b/docker/Dockerfile
@@ -1,4 +1,4 @@
-FROM postgres:14
+FROM postgres:16
 RUN apt-get update && apt-get upgrade -y
 
 ENV build_deps ca-certificates \
@@ -13,10 +13,10 @@ ENV build_deps ca-certificates \
 
 RUN apt-get install -y --no-install-recommends $build_deps pkg-config cmake
 
-WORKDIR /home/spark
+WORKDIR /home/spa5k
 
-ENV HOME=/home/spark \
-  PATH=/home/spark/.cargo/bin:$PATH
+ENV HOME=/home/spa5k \
+  PATH=/home/spa5k/.cargo/bin:$PATH
 RUN chown postgres:postgres /home/spark
 USER postgres
 
@@ -27,9 +27,9 @@ RUN \
   cargo --version
 
 # PGX
-RUN cargo install cargo-pgx
+RUN cargo install cargo-pgrx
 
-RUN cargo pgx init --pg14 $(which pg_config)
+RUN cargo pgx init --pg16 $(which pg_config)
 
 USER root
 
diff --git a/dprint.json b/dprint.json
deleted file mode 100644
index bb3430f..0000000
--- a/dprint.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
-  "json": {},
-  "markdown": {},
-  "toml": {},
-  "includes": [
-    "**/*.{ts,tsx,js,jsx,cjs,mjs,json,md,toml,rs,sql}"
-  ],
-  "excludes": [
-    "**/node_modules",
-    "**/*-lock.json",
-    "target"
-  ],
-  "plugins": [
-    "https://plugins.dprint.dev/json-0.15.3.wasm",
-    "https://plugins.dprint.dev/markdown-0.13.3.wasm",
-    "https://plugins.dprint.dev/toml-0.5.4.wasm",
-    "https://plugins.dprint.dev/rustfmt-0.6.2.json@886c6f3161cf020c2d75160262b0f56d74a521e05cfb91ec4f956650c8ca76ca",
-    "https://plugins.dprint.dev/sql-0.1.2.wasm"
-  ]
-}
diff --git a/infra/docker/base-pkg-alpine3.18-amd64.Dockerfile b/infra/docker/base-pkg-alpine3.18-amd64.Dockerfile
new file mode 100644
index 0000000..a442142
--- /dev/null
+++ b/infra/docker/base-pkg-alpine3.18-amd64.Dockerfile
@@ -0,0 +1,55 @@
+FROM alpine:latest AS builder
+
+# Allow for overriding rust toolcahin version
+ARG RUST_TOOLCHAIN_VERSION=1.76
+ENV RUST_TOOLCHAIN_VERSION=$RUST_TOOLCHAIN_VERSION
+
+# Allow for overriding of PGRX PG version that is used
+ARG PGRX_PG_VERSION=pg16
+ENV PGRX_PG_VERSION=$PGRX_PG_VERSION
+
+# Allow overriding features so that this file can be used to build
+# different crate features. By default since this is a 16.2 base package
+# we expect to build with crate feature 'pg16'
+ARG CARGO_FEATURES=pg16
+ENV CARGO_FEATURES=$CARGO_FEATURES
+
+# Install OS deps
+RUN apk add --no-cache \
+    alpine-sdk \
+    bash \
+    bison \
+    clang \
+    clang-dev \
+    clang-libs \
+    coreutils \
+    flex \
+    icu-dev \
+    linux-headers \
+    musl-dev \
+    openssl-dev \
+    perl \
+    readline \
+    readline-dev \
+    rustup \
+    zlib-dev
+
+# Install Rust & related deps
+RUN rustup-init -y --profile minimal --default-toolchain $RUST_TOOLCHAIN_VERSION
+ENV PATH="/root/.cargo/bin:${PATH}"
+RUN cargo install just cargo-get
+
+# Install pgrx
+# (disabling the static C runtime is required since pgrx requires dynamic linking w/ libssl and libcrypto)
+RUN RUSTFLAGS="-Ctarget-feature=-crt-static" cargo install --locked cargo-pgrx@0.11.4
+
+# Copy in uids code
+WORKDIR /uids
+COPY . .
+
+# Initialize pgrx
+ENV PGRX_IGNORE_RUST_VERSIONS=y
+RUN just pgrx-init
+
+# Build the package
+RUN RUSTFLAGS="-Ctarget-feature=-crt-static" just build package
\ No newline at end of file
diff --git a/infra/docker/builder-gnu.Dockerfile b/infra/docker/builder-gnu.Dockerfile
new file mode 100644
index 0000000..97df053
--- /dev/null
+++ b/infra/docker/builder-gnu.Dockerfile
@@ -0,0 +1,77 @@
+# rust:1.76.0-slim-bullseye as of 2024/03/06
+FROM rust:1.76.0-slim-bullseye
+
+ENV CARGO_HOME=/usr/local/cargo
+ENV CARGO_TARGET_DIR=/usr/local/build/target
+ENV SCCACHE_DIR=/usr/local/sccache
+# Disable cargo incremental builds since sccache can't support them
+ENV CARGO_INCREMENTAL=0
+
+# Install deps
+RUN apt update && apt install -y libssl-dev git openssh-client pkg-config curl ca-certificates gnupg wget
+RUN cargo install sccache --locked
+
+ENV CARGO_BUILD_RUSTC_WRAPPER=/usr/local/cargo/bin/sccache
+
+##################
+# Setup Postgres #
+##################
+
+# Add postgresql.org PGP keys
+RUN wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add
+
+# Add postgres repo
+RUN sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt bullseye-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
+
+# Install pg15
+RUN apt -y update && apt -y upgrade && apt install -y postgresql-15
+
+# Install NodeJS
+RUN set -uex; \
+    apt-get update; \
+    apt-get install -y ca-certificates curl gnupg; \
+    mkdir -p /etc/apt/keyrings; \
+    curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key \
+     | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg; \
+    NODE_MAJOR=20; \
+    echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" \
+     > /etc/apt/sources.list.d/nodesource.list; \
+    apt-get update; \
+    apt-get install nodejs -y;
+
+# Install dependencies for building postgres, NodeJS, etc
+RUN apt-get update && \
+    apt-get install -y --no-install-recommends ca-certificates \
+    git build-essential libpq-dev \
+    postgresql postgresql-server-dev-15 \
+    curl libreadline6-dev zlib1g-dev libclang-dev \
+    pkg-config cmake nodejs
+
+# Add postgres user to root group
+RUN useradd --user-group --system --create-home --no-log-init uids && \
+    usermod -aG sudo uids && \
+    chown -R uids /home/uids && \
+    addgroup uids root
+
+# Allow writing to postgres extensions folder
+RUN chmod g+w -R /usr/share/postgresql/**/extension && \
+    chmod g+w -R /usr/lib/postgresql/**/lib
+
+###############
+# Setup Cargo #
+###############
+
+# Allow writing to cargo cache by uids (now part of root group)
+RUN chmod g+w -R /usr/local/cargo
+RUN chmod g+w -R /usr/local/build
+
+RUN mkdir /usr/local/sccache
+RUN chmod g+w -R /usr/local/sccache
+
+# Install & Initialize pgrx
+# NOTE: pgrx must be reinitialized if cargo-pgrx changes
+RUN su uids -c "cargo install cargo-pgrx@0.11.4"
+RUN su uids -c "cargo pgrx init --pg15 download"
+
+# Install development/build/testing deps
+RUN su uids -c "cargo install just sccache cargo-cache cargo-get cargo-edit"
\ No newline at end of file
diff --git a/infra/docker/uids_postgres-pg15.7-alpine3.18-amd64.Dockerfile b/infra/docker/uids_postgres-pg15.7-alpine3.18-amd64.Dockerfile
new file mode 100644
index 0000000..b1d1f16
--- /dev/null
+++ b/infra/docker/uids_postgres-pg15.7-alpine3.18-amd64.Dockerfile
@@ -0,0 +1,45 @@
+#
+# NOTE: you must have the base packaging layer built for this image to work
+# you can build this from scratch with `just build-base-pkg-image`
+#
+# `cargo pgrx init` is run in the base-pkg, so it contains the versions of pg that will be used.
+#
+FROM ghcr.io/spa5k/uids-postgres/base-pkg:0.1.x-alpine3.18-amd64 AS builder
+
+ARG USER
+ENV USER=$USER
+
+ARG PGRX_PG_VERSION=pg15
+ENV PGRX_PG_VERSION=$PGRX_PG_VERSION
+
+ARG PKG_PG_VERSION=15.7
+ENV PKG_PG_VERSION=$PKG_PG_VERSION
+
+ENV PKG_TARBALL_SUFFIX="-musl"
+
+# Re-run the build with the latest code
+WORKDIR /uids
+COPY . .
+RUN RUSTFLAGS="-Ctarget-feature=-crt-static" just build package
+
+FROM postgres:15.7-alpine3.18
+
+# NOTE: PGRX_PG_VERSION is defined via base-pkg:pg15.5-alpine3.18-amd64
+ARG PGRX_PG_VERSION=pg15
+ARG PGIDKIT_VERSION
+ARG PGIDKIT_REVISION
+
+# Install packaged uids for system postgres
+COPY --from=builder /uids/uids-*-musl.tar.gz /tmp
+RUN tar -C /usr/local --strip-components=1 -xvf /tmp/uids-*-musl.tar.gz
+
+LABEL org.opencontainers.image.authors="spa5k"
+LABEL org.opencontainers.image.description="A distribution of the base postgres image, with uids pre-installed."
+LABEL org.opencontainers.image.documentation="https://github.com/spa5k/uids-postgres#readme"
+LABEL org.opencontainers.image.licenses="Apache-2.0"
+LABEL org.opencontainers.image.revision=$PGIDKIT_REVISION
+LABEL org.opencontainers.image.source="https://github.com/spa5k/uids-postgres"
+LABEL org.opencontainers.image.title="Postgres + uids"
+LABEL org.opencontainers.image.url="https://github.com/spa5k/uids-postgres"
+LABEL org.opencontainers.image.vendor="spa5k"
+LABEL org.opencontainers.image.version=v${PGIDKIT_VERSION}
\ No newline at end of file
diff --git a/infra/docker/uids_postgres-pg16.3-alpine3.18-amd64.Dockerfile b/infra/docker/uids_postgres-pg16.3-alpine3.18-amd64.Dockerfile
new file mode 100644
index 0000000..945cb61
--- /dev/null
+++ b/infra/docker/uids_postgres-pg16.3-alpine3.18-amd64.Dockerfile
@@ -0,0 +1,45 @@
+#
+# NOTE: you must have the base packaging layer built for this image to work
+# you can build this from scratch with `just build-base-pkg-image`
+#
+# `cargo pgrx init` is run in the base-pkg, so it contains the versions of pg that will be used.
+#
+FROM ghcr.io/spa5k/uids-postgres/base-pkg:0.1.x-alpine3.18-amd64 AS builder
+
+ARG USER
+ENV USER=$USER
+
+ARG PGRX_PG_VERSION=pg16
+ENV PGRX_PG_VERSION=$PGRX_PG_VERSION
+
+ARG PKG_PG_VERSION=16.3
+ENV PKG_PG_VERSION=$PKG_PG_VERSION
+
+ENV PKG_TARBALL_SUFFIX="-musl"
+
+# Re-run the build with the latest code
+WORKDIR /uids
+COPY . .
+RUN RUSTFLAGS="-Ctarget-feature=-crt-static" just build package
+
+FROM postgres:16-alpine
+
+# NOTE: PGRX_PG_VERSION is defined via base-pkg:pg16.5-alpine3.18-amd64
+ARG PGRX_PG_VERSION=pg16
+ARG PGIDKIT_VERSION
+ARG PGIDKIT_REVISION
+
+# Install packaged uids for system postgres
+COPY --from=builder /uids/uids-*-musl.tar.gz /tmp
+RUN tar -C /usr/local --strip-components=1 -xvf /tmp/uids-*-musl.tar.gz
+
+LABEL org.opencontainers.image.authors="spa5k"
+LABEL org.opencontainers.image.description="A distribution of the base postgres image, with uids pre-installed."
+LABEL org.opencontainers.image.documentation="https://github.com/spa5k/uids-postgres#readme"
+LABEL org.opencontainers.image.licenses="Apache-2.0"
+LABEL org.opencontainers.image.revision=$PGIDKIT_REVISION
+LABEL org.opencontainers.image.source="https://github.com/spa5k/uids-postgres"
+LABEL org.opencontainers.image.title="Postgres + uids"
+LABEL org.opencontainers.image.url="https://github.com/spa5k/uids-postgres"
+LABEL org.opencontainers.image.vendor="spa5k"
+LABEL org.opencontainers.image.version=v${PGIDKIT_VERSION}
\ No newline at end of file
diff --git a/justfile b/justfile
new file mode 100644
index 0000000..64b4549
--- /dev/null
+++ b/justfile
@@ -0,0 +1,267 @@
+# Choose sell based on platform
+shell := if os() == "macos" { "zsh" } else { "bash" }
+
+docker := env_var_or_default("DOCKER", "docker")
+git := env_var_or_default("GIT", "git")
+tar := env_var_or_default("TAR", "tar")
+strip := env_var_or_default("STRIP", "strip")
+just := env_var_or_default("JUST", just_executable())
+
+cargo := env_var_or_default("CARGO", "cargo")
+cargo_get := env_var_or_default("CARGO_GET", "cargo-get")
+cargo_generate_rpm := env_var_or_default("CARGO_GENERATE_RPM", "cargo-generate-rpm")
+cargo_watch := env_var_or_default("CARGO_WATCH", "cargo-watch")
+cargo_profile := env_var_or_default("CARGO_PROFILE", "")
+cargo_profile_arg := if cargo_profile != "" {
+  "--profile " + cargo_profile
+} else {
+  ""
+}
+cargo_features := env_var_or_default("CARGO_FEATURES", "")
+cargo_features_arg := if cargo_features != "" {
+  "--no-default-features --features " + cargo_features
+} else {
+  ""
+}
+
+changelog_file_path := absolute_path(justfile_directory() / "CHANGELOG")
+
+pkg_pg_version := env_var_or_default("PKG_PG_VERSION", "16.2")
+pkg_pg_config_path := env_var_or_default("PKG_PG_CONFIG_PATH", "~/.pgrx/" + pkg_pg_version + "/pgrx-install/bin/pg_config")
+pkg_tarball_suffix := env_var_or_default("PKG_TARBALL_SUFFIX", "")
+
+pgrx_pg_version := env_var_or_default("PGRX_PG_VERSION", "pg16")
+pgrx_pkg_path_prefix := env_var_or_default("PGRX_PKG_PATH_PREFIX", "target")
+# If /root, 'home' does not appear in the generated prefix
+pkg_user_dir_prefix := if docker_build_user == "root" { docker_build_user } else { "home/" + docker_build_user }
+pgrx_pkg_output_dir := pgrx_pkg_path_prefix / "release" / "uids-postgres" + pgrx_pg_version / pkg_user_dir_prefix / ".pgrx" / pkg_pg_version / "pgrx-install"
+
+docker_build_user := env_var_or_default('DOCKER_BUILD_USER', "root")
+
+default:
+    {{just}} --list
+
+###########
+# Tooling #
+###########
+
+_check-installed-version tool msg:
+    #!/usr/bin/env -S {{shell}} -euo pipefail
+    if [ -z "$(command -v {{tool}})" ]; then
+      echo "{{msg}}";
+      exit 1;
+    fi
+
+@_check-tool-cargo:
+    {{just}} _check-installed-version {{cargo}} "'cargo' not available, please install the Rust toolchain (see: https://github.com/rust-lang/cargo/)";
+
+@_check-tool-cargo-watch:
+    {{just}} _check-installed-version {{cargo_watch}} "'cargo-watch' not available, please install cargo-watch (https://github.com/passcod/cargo-watch)"
+
+@_check-tool-cargo-get:
+    {{just}} _check-installed-version {{cargo_get}} "'cargo-get' not available, please install cargo-get (https://crates.io/crates/cargo-get)"
+
+@_check-tool-strip:
+    {{just}} _check-installed-version {{strip}} "'strip' not available, please install strip (https://www.man7.org/linux/man-pages/man1/strip.1.html)"
+
+@_check-tool-cargo-generate-rpm:
+    {{just}} _check-installed-version {{cargo_generate_rpm}} "'cargo-generate-rpm' not available, please install cargo-generate-rpm (https://crates.io/crates/cargo-generate-rpm)"
+
+#########
+# Build #
+#########
+
+version := env_var_or_default("VERSION", `cargo get package.version`)
+revision := env_var_or_default("REVISION", `git rev-parse --short HEAD`)
+
+@get-version: _check-tool-cargo-get
+    echo -n {{version}}
+
+@get-revision: _check-tool-cargo-get
+    echo -n {{revision}}
+
+print-version:
+    #!/usr/bin/env -S {{shell}} -euo pipefail
+    echo -n `{{just}} get-version`
+
+print-revision:
+    #!/usr/bin/env -S {{shell}} -euo pipefail
+    echo -n `{{just}} get-revision`
+
+print-pkg-output-dir:
+    echo -n {{pgrx_pkg_output_dir}}
+
+changelog:
+    {{git}} cliff --unreleased --tag={{version}} --prepend={{changelog_file_path}}
+
+# Set the version on the package
+set-version version:
+    {{cargo}} set-version {{version}}
+
+lint:
+    {{cargo}} clippy {{cargo_features_arg}} {{cargo_profile_arg}} --all-targets
+
+build:
+    {{cargo}} build {{cargo_features_arg}} {{cargo_profile_arg}}
+
+build-release:
+    {{cargo}} build --release {{cargo_features_arg}}
+
+build-watch: _check-tool-cargo _check-tool-cargo-watch
+    {{cargo_watch}} -x "build $(CARGO_BUILD_FLAGS)" --watch src
+
+build-test-watch: _check-tool-cargo _check-tool-cargo-watch
+    {{cargo_watch}} -x "test $(CARGO_BUILD_FLAGS)" --watch src
+
+build-package:
+    PGRX_IGNORE_RUST_VERSIONS=y {{cargo}} pgrx package --pg-config {{pkg_pg_config_path}} -vvv
+
+package: build-package
+    mkdir -p pkg/uids-postgres$({{just}} print-version)
+    cp -r $({{just}} print-pkg-output-dir)/* pkg/uids-postgres$({{just}} print-version)
+    {{tar}} -C pkg -cvf uids-postgres$(just print-version){{pkg_tarball_suffix}}.tar.gz  uids-postgres$({{just}} print-version)
+
+test:
+    {{cargo}} test {{cargo_profile_arg}}
+    {{cargo}} pgrx test
+
+pgrx-init:
+    #!/usr/bin/env -S {{shell}} -euo pipefail
+    if [ ! -d "{{pkg_pg_config_path}}" ]; then
+      echo "failed to find pgrx init dir [{{pkg_pg_config_path}}], running pgrx init...";
+      {{cargo}} pgrx init
+    fi
+
+##########
+# Docker #
+##########
+
+container_img_arch := env_var_or_default("CONTAINER_IMAGE_ARCH", "amd64")
+
+pg_image_version := env_var_or_default("POSTGRES_IMAGE_VERSION", "16.2")
+pg_os_image_version := env_var_or_default("POSTGRES_OS_IMAGE_VERSION", "alpine3.18")
+
+uids_postgres_image_name := env_var_or_default("UIDS_POSTGRES_IMAGE_NAME", "ghcr.io/spa5k/pg_idkit")
+uids_postgres_image_tag := env_var_or_default("POSGRES_IMAGE_VERSION", version + "-" + "pg" + pg_image_version + "-" + pg_os_image_version + "-" + container_img_arch)
+uids_postgres_image_tag_suffix := env_var_or_default("UIDS_POSTGRES_IMAGE_TAG_SUFFIX", "")
+uids_postgres_image_name_full := env_var_or_default("UIDS_POSTGRES_IMAGE_NAME_FULL", uids_postgres_image_name + ":" + uids_postgres_image_tag + uids_postgres_image_tag_suffix)
+uids_postgres_dockerfile_path := env_var_or_default("UIDS_POSTGRES_DOCKERFILE_PATH", "infra" / "docker" / uids_postgres_image_tag + ".Dockerfile")
+
+docker_password_path := env_var_or_default("DOCKER_PASSWORD_PATH", "secrets/docker/password.secret")
+docker_username_path := env_var_or_default("DOCKER_USERNAME_PATH", "secrets/docker/username.secret")
+docker_image_registry := env_var_or_default("DOCKER_IMAGE_REGISTRY", "ghcr.io/spa5k/pg_idkit")
+docker_config_dir := env_var_or_default("DOCKER_CONFIG", "secrets/docker")
+
+img_dockerfile_path := "infra" / "docker" / "uids-postgrespg" + pg_image_version + "-" + pg_os_image_version + "-" + container_img_arch + ".Dockerfile"
+
+# Ensure that that a given file is present
+_ensure-file file:
+    #!/usr/bin/env -S {{shell}} -euo pipefail
+    if [ ! -f "{{file}}" ] ; then
+      echo "[error] file [{{file}}] is required, but missing";
+      exit 1;
+    fi;
+
+# Log in with docker using local credentials
+docker-login:
+    {{just}} _ensure-file {{docker_password_path}}
+    {{just}} _ensure-file {{docker_username_path}}
+    cat {{docker_password_path}} | {{docker}} login {{docker_image_registry}} -u `cat {{docker_username_path}}` --password-stdin
+    cp {{docker_config_dir}}/config.json {{docker_config_dir}}/.dockerconfigjson
+
+docker_platform_arg := env_var_or_default("DOCKER_PLATFORM_ARG", "")
+docker_progress_arg := env_var_or_default("DOCKER_PROGRESS_ARG", "")
+
+##########################
+# Docker Image - builder #
+##########################
+#
+# This image is used as a cache for speeding up CI builds,
+# and for performing builds when building release artifacts
+#
+
+builder_gnu_dockerfile_path := env_var_or_default("BUILDER_DOCKERFILE_PATH", "infra" / "docker" / "builder-gnu.Dockerfile")
+builder_gnu_image_name := env_var_or_default("BUILDER_IMAGE_NAME", "ghcr.io/spa5k/pg_idkit/builder-gnu")
+builder_gnu_image_tag := env_var_or_default("BUILDER_IMAGE_TAG", "0.1.x")
+builder_gnu_image_name_full := env_var_or_default("BUILDER_IMAGE_NAME_FULL", builder_gnu_image_name + ":" + builder_gnu_image_tag)
+
+## TODO: uncomment and edit build-builder-image once musl machinery is available
+## https://github.com/spa5k/pg_idkit/issues/55
+#
+# builder_musl_dockerfile_path := env_var_or_default("BUILDER_DOCKERFILE_PATH", "infra" / "docker" / "builder-musl.Dockerfile")
+# builder_musl_image_name := env_var_or_default("BUILDER_IMAGE_NAME", "ghcr.io/spa5k/pg_idkit/builder-musl")
+# builder_musl_image_tag := env_var_or_default("BUILDER_IMAGE_TAG", "0.1.x")
+# builder_musl_image_name_full := env_var_or_default("BUILDER_IMAGE_NAME_FULL", builder_musl_image_name + ":" + builder_musl_image_tag)
+
+# Build the docker image used in BUILDER
+build-builder-image:
+    {{docker}} build -f {{builder_gnu_dockerfile_path}} -t {{builder_gnu_image_name_full}} .
+
+# Push the docker image used in BUILDER (to GitHub Container Registry)
+push-builder-image:
+    {{docker}} push {{builder_gnu_image_name_full}}
+
+###########################
+# Docker Image - base-pkg #
+###########################
+#
+# This image is used as a base for packaging flows, usually while building
+# the end-user facing Docker image that is contains Postgres & pg_idkit
+#
+
+# Determine the Dockerfile to use when building the packaging utility base image
+base_pkg_dockerfile_path := "infra/docker/base-pkg-" + pg_os_image_version + "-" + container_img_arch + ".Dockerfile"
+base_pkg_image_name := env_var_or_default("PKG_IMAGE_NAME", "ghcr.io/spa5k/pg_idkit/base-pkg")
+base_pkg_version := env_var_or_default("PKG_IMAGE_NAME", "0.1.x")
+base_pkg_image_tag := env_var_or_default("POSGRES_IMAGE_VERSION", base_pkg_version + "-" + pg_os_image_version + "-" + container_img_arch)
+base_pkg_image_name_full := env_var_or_default("PKG_IMAGE_NAME_FULL", base_pkg_image_name + ":" + base_pkg_image_tag)
+
+# Build the base image for packaging
+build-base-pkg-image:
+      {{docker}} build --build-arg USER={{docker_build_user}} -f {{base_pkg_dockerfile_path}} . -t {{base_pkg_image_name_full}};
+
+# Push the base image for packaging
+push-base-pkg-image:
+      {{docker}} push {{base_pkg_image_name_full}}
+
+###########################
+# Docker Image - pg_idkit #
+###########################
+#
+# This image is the pg_idkit image itself, normally built FROM
+# a image of base-pkg
+#
+
+# Build the docker image for pg_idkit
+build-image:
+    {{docker}} build {{docker_platform_arg}} {{docker_progress_arg}} -f {{img_dockerfile_path}} -t {{uids_postgres_image_name_full}} --build-arg USER={{docker_build_user}} --build-arg UIDS_POSTGRES_REVISION={{revision}} --build-arg UIDS_POSTGRES_VERSION={{uids_postgres_image_tag}} .
+
+# Push the docker image for pg_idkit
+push-image:
+    {{docker}} push {{uids_postgres_image_name_full}}
+
+#######
+# RPM #
+#######
+
+rpm_arch := env_var_or_default("RPM_ARCH", "x86_64")
+
+rpm_file_name := env_var_or_default("RPM_OUTPUT_PATH", "uids-postgres" + version + "-" + pgrx_pg_version + "." + rpm_arch + ".rpm")
+rpm_output_path := "target" / "generate-rpm" / rpm_file_name
+
+# Cargo.toml depends on this file being at the location below.
+rpm_scratch_location := "/tmp/pg_idkit/rpm/scratch"
+
+# Build an RPM distribution for pg_idkit
+build-rpm: _check-tool-strip _check-tool-cargo-generate-rpm
+    CARGO_FEATURES={{pgrx_pg_version}} {{just}} package
+    {{strip}} -s {{pgrx_pkg_output_dir}}/lib/postgresql/pg_idkit.so
+    mkdir -p {{rpm_scratch_location}}
+    cp -r {{pgrx_pkg_output_dir}} {{rpm_scratch_location}}
+    {{cargo_generate_rpm}} --variant {{pgrx_pg_version}}
+
+@print-rpm-output-file-name:
+    echo -n {{rpm_file_name}}
+
+@print-rpm-output-path:
+    echo -n {{rpm_output_path}}
\ No newline at end of file
diff --git a/src/cuid2.rs b/src/cuid2.rs
new file mode 100644
index 0000000..4d55402
--- /dev/null
+++ b/src/cuid2.rs
@@ -0,0 +1,36 @@
+pub mod cuid2_rs {
+    use cuid2;
+    use pgrx::prelude::*;
+
+    #[pg_extern]
+    pub(crate) fn generate_cuid2() -> String {
+        let id = cuid2::create_id();
+        id.to_string()
+    }
+
+    #[pg_extern]
+    pub(crate) fn check_cuid2(id_str: &str) -> bool {
+        cuid2::is_cuid2(id_str)
+    }
+
+    // tests
+    #[cfg(any(test, feature = "pg_test"))]
+    #[pgrx::pg_schema]
+    mod tests {
+        use pgrx::pg_test;
+
+        use crate::cuid2::cuid2_rs::{check_cuid2, generate_cuid2};
+
+        #[pg_test]
+        fn test_generate_cuid2() {
+            let cuid2_string: String = generate_cuid2();
+            assert!(cuid2_string.len() == 24);
+        }
+
+        #[pg_test]
+        fn test_check_cuid2() {
+            let cuid2_string: String = generate_cuid2();
+            assert!(check_cuid2(&cuid2_string));
+        }
+    }
+}
diff --git a/src/ksuid.rs b/src/ksuid.rs
index 71c0059..1598f64 100644
--- a/src/ksuid.rs
+++ b/src/ksuid.rs
@@ -1,5 +1,5 @@
 pub mod ksuid_rs {
-    use pgx::*;
+    use pgrx::prelude::*;
     use svix_ksuid::{KsuidLike, KsuidMs};
 
     #[pg_extern]
@@ -13,4 +13,25 @@ pub mod ksuid_rs {
         let ksuid_bytes = KsuidMs::new(None, None);
         ksuid_bytes.bytes().to_vec()
     }
+
+    // tests
+    #[cfg(any(test, feature = "pg_test"))]
+    #[pgrx::pg_schema]
+    mod tests {
+        use pgrx::pg_test;
+
+        // Test Ksuid length
+        #[pg_test]
+        fn test_generate_ksuid_length() {
+            let ksuid_string: String = crate::ksuid::ksuid_rs::generate_ksuid();
+            assert_eq!(ksuid_string.len(), 27);
+        }
+
+        // Test ksuid bytes
+        #[pg_test]
+        fn test_generate_ksuid_bytes() {
+            let ksuid_bytes: Vec<u8> = crate::ksuid::ksuid_rs::generate_ksuid_bytes();
+            assert_eq!(ksuid_bytes.len(), 20);
+        }
+    }
 }
diff --git a/src/lib.rs b/src/lib.rs
index 3d6dc09..c46e662 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,71 +1,19 @@
+mod cuid2;
 mod ksuid;
 mod nanoid;
+mod pushid;
+mod timeflake;
+mod typeid;
 mod ulid;
+mod uuid_v6;
+mod uuidv7;
 
-use pgx::*;
+use pgrx::prelude::*;
 
-pg_module_magic!();
-
-#[cfg(any(test, feature = "pg_test"))]
-#[pg_schema]
-mod tests {
-    use pgx::*;
-
-    #[pg_test]
-    fn test_generate_ulid() {
-        let ulid_string: String = crate::ulid::ulid_rs::generate_ulid();
-        assert_eq!(ulid_string.len(), 26);
-    }
-
-    #[pg_test]
-    fn test_generate_ulid_from_string() {
-        let ulid_string: String = "01CAT3X5Y5G9A62F1rFA6Tnice".to_string();
-        // copy of ulid_string
-        let ulid_from_string: String = crate::ulid::ulid_rs::generate_ulid_from_string(ulid_string);
-        assert_eq!(ulid_from_string, "01CAT3X5Y5G9A62F1RFA6TN1CE");
-    }
-
-    #[pg_test]
-    fn test_generate_ulid_bytes() {
-        let ulid_bytes: Vec<u8> = crate::ulid::ulid_rs::generate_ulid_bytes();
-        assert_eq!(ulid_bytes.len(), 16);
-    }
-
-    // Test Ksuid length
-    #[pg_test]
-    fn test_generate_ksuid_length() {
-        let ksuid_string: String = crate::ksuid::ksuid_rs::generate_ksuid();
-        assert_eq!(ksuid_string.len(), 27);
-    }
-
-    // Test ksuid bytes
-    #[pg_test]
-    fn test_generate_ksuid_bytes() {
-        let ksuid_bytes: Vec<u8> = crate::ksuid::ksuid_rs::generate_ksuid_bytes();
-        assert_eq!(ksuid_bytes.len(), 20);
-    }
-
-    // Test nanoid length
-    #[pg_test]
-    fn test_generate_nanoid_length() {
-        let nanoid_string: String = crate::nanoid::nanoid_rs::generate_nanoid_length(10);
-        assert_eq!(nanoid_string.len(), 10);
-    }
-
-    // test nanoid without legnth
-    #[pg_test]
-    fn test_generate_nanoid() {
-        let nanoid_string: String = crate::nanoid::nanoid_rs::generate_nanoid();
-        assert_eq!(nanoid_string.len(), 21);
-    }
-
-    #[pg_test]
-    fn test_generate_nanoida() {
-        let nanoid_string: String = crate::nanoid::nanoid_rs::generate_nanoid_c("1234567890abcdef");
-        assert_eq!(nanoid_string.len(), 21);
-    }
-}
+pgrx::pg_module_magic!();
 
+/// This module is required by `cargo pgrx test` invocations.
+/// It must be visible at the root of your extension crate.
 #[cfg(test)]
 pub mod pg_test {
     pub fn setup(_options: Vec<&str>) {
diff --git a/src/nanoid.rs b/src/nanoid.rs
index b544a52..7f1c6fa 100644
--- a/src/nanoid.rs
+++ b/src/nanoid.rs
@@ -1,6 +1,6 @@
 pub mod nanoid_rs {
     use nanoid::nanoid;
-    use pgx::*;
+    use pgrx::prelude::*;
 
     #[pg_extern]
     pub(crate) fn generate_nanoid() -> String {
@@ -30,4 +30,32 @@ pub mod nanoid_rs {
         let id = nanoid!(21, &alphabets_vec);
         id
     }
+
+    // tests
+    #[cfg(any(test, feature = "pg_test"))]
+    #[pgrx::pg_schema]
+    mod tests {
+        use pgrx::pg_test;
+
+        // Test Nanoid length
+        #[pg_test]
+        fn test_generate_nanoid_length() {
+            let nanoid_string: String = crate::nanoid::nanoid_rs::generate_nanoid_length(10);
+            assert_eq!(nanoid_string.len(), 10);
+        }
+
+        // test nanoid without legnth
+        #[pg_test]
+        fn test_generate_nanoid() {
+            let nanoid_string: String = crate::nanoid::nanoid_rs::generate_nanoid();
+            assert_eq!(nanoid_string.len(), 21);
+        }
+
+        #[pg_test]
+        fn test_generate_nanoid_custom() {
+            let nanoid_string: String =
+                crate::nanoid::nanoid_rs::generate_nanoid_c("1234567890abcdef");
+            assert_eq!(nanoid_string.len(), 21);
+        }
+    }
 }
diff --git a/src/pushid.rs b/src/pushid.rs
new file mode 100644
index 0000000..b4ebb53
--- /dev/null
+++ b/src/pushid.rs
@@ -0,0 +1,36 @@
+pub mod pushid_rs {
+    use pgrx::*;
+    use pushid::PushId;
+    use pushid::PushIdGen;
+
+    /// Generate a PushId
+    #[pg_extern]
+    fn generate_pushid() -> String {
+        PushId::new().get_id()
+    }
+
+    /// Generate a PushId as text
+    #[pg_extern]
+    fn generate_pushid_text() -> String {
+        generate_pushid()
+    }
+
+    // tests
+    #[cfg(any(test, feature = "pg_test"))]
+    #[pg_schema]
+    mod tests {
+        use pgrx::*;
+
+        #[pg_test]
+        fn test_pushid_len() {
+            let generated = crate::pushid::pushid_rs::generate_pushid();
+            assert_eq!(generated.len(), 20);
+        }
+
+        #[pg_test]
+        fn test_pushid_text_len() {
+            let generated = crate::pushid::pushid_rs::generate_pushid_text();
+            assert_eq!(generated.len(), 20);
+        }
+    }
+}
diff --git a/src/timeflake.rs b/src/timeflake.rs
new file mode 100644
index 0000000..0dc77b3
--- /dev/null
+++ b/src/timeflake.rs
@@ -0,0 +1,49 @@
+pub mod timeflake_rs {
+    use pgrx::prelude::*;
+    use timeflake_rs::Timeflake;
+
+    #[pg_extern]
+    pub(crate) fn generate_timeflake() -> String {
+        let result = Timeflake::random();
+        result.unwrap().to_string()
+    }
+
+    #[pg_extern]
+    pub(crate) fn generate_timeflake_bytes() -> Vec<u8> {
+        let result = Timeflake::random();
+        result.unwrap().as_uuid().as_bytes().to_vec()
+    }
+
+    #[pg_extern]
+    pub fn generate_timeflake_uuid() -> pgrx::Uuid {
+        pgrx::Uuid::from_slice(Timeflake::random().unwrap().as_uuid().as_bytes()).unwrap()
+    }
+
+    #[cfg(any(test, feature = "pg_test"))]
+    #[pgrx::pg_schema]
+    mod tests {
+        use pgrx::pg_test;
+
+        use crate::timeflake::timeflake_rs::{
+            generate_timeflake, generate_timeflake_bytes, generate_timeflake_uuid,
+        };
+
+        #[pg_test]
+        fn test_generate_timeflake() {
+            let timeflake_string: String = generate_timeflake();
+            assert!(timeflake_string.len() == 36);
+        }
+
+        #[pg_test]
+        fn test_generate_timeflake_bytes() {
+            let timeflake_bytes: Vec<u8> = generate_timeflake_bytes();
+            assert!(timeflake_bytes.len() == 16);
+        }
+
+        #[pg_test]
+        fn test_generate_timeflake_uuid() {
+            let timeflake_uuid: pgrx::Uuid = generate_timeflake_uuid();
+            assert!(timeflake_uuid.len() == 16);
+        }
+    }
+}
diff --git a/src/typeid.rs b/src/typeid.rs
new file mode 100644
index 0000000..505e0f8
--- /dev/null
+++ b/src/typeid.rs
@@ -0,0 +1,50 @@
+pub mod typeid_rs {
+    use pgrx::prelude::*;
+    use type_safe_id::{DynamicType, TypeSafeId};
+
+    #[pg_extern]
+    pub(crate) fn generate_typeid(prefix: &str) -> String {
+        let dynamic_type = DynamicType::new(prefix).expect("invalid prefix");
+        let id: TypeSafeId<DynamicType> = TypeSafeId::new_with_type(dynamic_type);
+        id.to_string()
+    }
+
+    #[pg_extern]
+    pub(crate) fn check_typeid(prefix: &str, id_str: &str) -> bool {
+        let id: TypeSafeId<DynamicType> = id_str.parse().expect("invalid id");
+        id.type_prefix() == prefix
+    }
+
+    // tests
+    #[cfg(any(test, feature = "pg_test"))]
+    #[pgrx::pg_schema]
+    mod tests {
+        use pgrx::pg_test;
+
+        // Test TypeId length
+        #[pg_test]
+        fn test_generate_typeid_length() {
+            let typeid_string: String = crate::typeid::typeid_rs::generate_typeid("custom");
+            assert_eq!(typeid_string.len(), 33);
+        }
+
+        // Test TypeId prefix
+        #[pg_test]
+        fn test_generate_typeid_prefix() {
+            let typeid_string: String = crate::typeid::typeid_rs::generate_typeid("custom");
+            assert!(typeid_string.starts_with("custom_"));
+        }
+
+        // Test TypeId check
+        #[pg_test]
+        fn test_check_typeid() {
+            let prefix = "custom";
+            let id: String = crate::typeid::typeid_rs::generate_typeid(prefix);
+            let is_match: bool = crate::typeid::typeid_rs::check_typeid(prefix, &id);
+            assert!(is_match);
+
+            let is_not_match: bool = crate::typeid::typeid_rs::check_typeid("other", &id);
+            assert!(!is_not_match);
+        }
+    }
+}
diff --git a/src/ulid.rs b/src/ulid.rs
index 9c2d73d..c401c78 100644
--- a/src/ulid.rs
+++ b/src/ulid.rs
@@ -1,7 +1,7 @@
 pub mod ulid_rs {
     use std::str::FromStr;
 
-    use pgx::*;
+    use pgrx::prelude::*;
     use rusty_ulid::{generate_ulid_bytes as ulid_bytes, Ulid};
 
     use rusty_ulid::generate_ulid_string;
@@ -23,4 +23,35 @@ pub mod ulid_rs {
         let result = Ulid::from_str(&from_str);
         result.unwrap().to_string()
     }
+
+    // tests
+    #[cfg(any(test, feature = "pg_test"))]
+    #[pgrx::pg_schema]
+    mod tests {
+        use pgrx::pg_test;
+
+        // Test Ulid length
+        #[pg_test]
+        fn test_generate_ulid_length() {
+            let ulid_string: String = crate::ulid::ulid_rs::generate_ulid();
+            assert_eq!(ulid_string.len(), 26);
+        }
+
+        // Test Ulid bytes
+        #[pg_test]
+        fn test_generate_ulid_bytes() {
+            let ulid_bytes: Vec<u8> = crate::ulid::ulid_rs::generate_ulid_bytes();
+            assert_eq!(ulid_bytes.len(), 16);
+        }
+
+        // Test Ulid from string
+        #[pg_test]
+        fn test_generate_ulid_from_string() {
+            let ulid_string: String = "01CAT3X5Y5G9A62F1rFA6Tnice".to_string();
+            // copy of ulid_string
+            let ulid_from_string: String =
+                crate::ulid::ulid_rs::generate_ulid_from_string(ulid_string);
+            assert_eq!(ulid_from_string, "01CAT3X5Y5G9A62F1RFA6TN1CE");
+        }
+    }
 }
diff --git a/src/uuid_v6.rs b/src/uuid_v6.rs
new file mode 100644
index 0000000..499f2a9
--- /dev/null
+++ b/src/uuid_v6.rs
@@ -0,0 +1,66 @@
+pub mod uuidv6_rs {
+    use std::io::{Error as IoError, ErrorKind};
+
+    use getrandom::getrandom;
+    use pgrx::pg_extern;
+    use uuid::Uuid;
+
+    /// Generate a new UUIDv6
+    fn new_uuidv6() -> Uuid {
+        let mut buf = [0u8; 6];
+        let res = getrandom(&mut buf);
+        if res.is_err() {
+            panic!("failed to get random bytes for building uuidv6");
+        }
+        Uuid::now_v6(&buf)
+    }
+
+    /// Generate a UUID v6
+    #[pg_extern]
+    pub(crate) fn generate_uuidv6() -> String {
+        new_uuidv6().as_hyphenated().to_string()
+    }
+
+    /// Generate a UUID v6, producing a Postgres text object
+    #[pg_extern]
+    pub(crate) fn generate_uuidv6_text() -> String {
+        generate_uuidv6()
+    }
+
+    /// Generate a UUID v6, producing a Postgres uuid object
+    #[pg_extern]
+    pub(crate) fn generate_uuidv6_uuid() -> pgrx::Uuid {
+        pgrx::Uuid::from_slice(new_uuidv6().as_bytes())
+            .map_err(|e| IoError::new(ErrorKind::Other, e))
+            .unwrap()
+    }
+
+    #[cfg(any(test, feature = "pg_test"))]
+    #[pgrx::pg_schema]
+    mod tests {
+        use pgrx::pg_test;
+
+        use crate::uuid_v6::uuidv6_rs::{generate_uuidv6, generate_uuidv6_uuid};
+
+        /// Basic length test
+        #[pg_test]
+        fn test_uuidv6_len() {
+            assert_eq!(generate_uuidv6().len(), 36);
+        }
+
+        /// Basic length test for bytes
+        #[pg_test]
+        fn test_uuidv6_len_uuid() {
+            assert_eq!(generate_uuidv6_uuid().len(), 16);
+        }
+
+        /// Check version integer in UUID string
+        #[pg_test]
+        fn test_uuidv6_version_int() {
+            let generated = generate_uuidv6();
+            let c9 = generated.chars().nth(14);
+            assert!(c9.is_some());
+            assert_eq!(c9.unwrap(), '6');
+        }
+    }
+}
diff --git a/src/uuidv7.rs b/src/uuidv7.rs
new file mode 100644
index 0000000..81ac071
--- /dev/null
+++ b/src/uuidv7.rs
@@ -0,0 +1,74 @@
+pub mod uuidv7_rs {
+    use pgrx::prelude::*;
+    use uuid::Uuid;
+
+    #[pg_extern]
+    pub(crate) fn generate_uuidv7() -> String {
+        let uuid = Uuid::now_v7();
+        uuid.to_string()
+    }
+
+    #[pg_extern]
+    pub(crate) fn generate_uuidv7_bytes() -> Vec<u8> {
+        let uuid = Uuid::now_v7();
+        uuid.as_bytes().to_vec()
+    }
+
+    #[pg_extern]
+    pub fn generate_uuidv7_from_string(from_str: String) -> String {
+        let result = Uuid::parse_str(&from_str);
+        result.unwrap().to_string()
+    }
+
+    #[pg_extern]
+    pub fn parse_uuidv7(from_str: String) -> String {
+        let result = Uuid::parse_str(&from_str);
+        result.unwrap().to_string()
+    }
+
+    // tests
+    #[cfg(any(test, feature = "pg_test"))]
+    #[pgrx::pg_schema]
+    mod tests {
+        use pgrx::pg_test;
+
+        // Test UUIDv7 length
+        #[pg_test]
+        fn test_generate_uuidv7_length() {
+            let uuidv7_string: String = crate::uuidv7::uuidv7_rs::generate_uuidv7();
+            assert_eq!(uuidv7_string.len(), 36);
+        }
+
+        // Test UUIDv7 bytes
+        #[pg_test]
+        fn test_generate_uuidv7_bytes() {
+            let uuidv7_bytes: Vec<u8> = crate::uuidv7::uuidv7_rs::generate_uuidv7_bytes();
+            assert_eq!(uuidv7_bytes.len(), 16);
+        }
+
+        // Test UUIDv7 from string
+        #[pg_test]
+        fn test_generate_uuidv7_from_string() {
+            let uuidv7_string: String = "67e55044-10b1-426f-9247-bb680e5fe0c8".to_string();
+            // copy of uuidv7_string
+            let uuidv7_from_string: String =
+                crate::uuidv7::uuidv7_rs::generate_uuidv7_from_string(uuidv7_string);
+            assert_eq!(uuidv7_from_string, "67e55044-10b1-426f-9247-bb680e5fe0c8");
+        }
+
+        // Test UUIDv7 parse
+        #[pg_test]
+        fn test_parse_uuidv7() {
+            let uuidv7_string: String = "67e55044-10b1-426f-9247-bb680e5fe0c8".to_string();
+            let uuidv7: String = crate::uuidv7::uuidv7_rs::parse_uuidv7(uuidv7_string.clone());
+            assert_eq!(uuidv7, uuidv7_string);
+        }
+
+        #[pg_test]
+        fn test_generate_uuidv7() {
+            let uuid: String = crate::uuidv7::uuidv7_rs::generate_uuidv7();
+            assert_eq!(uuid.len(), 36); // UUIDv7 length
+            assert!(uuid.contains('-')); // UUID format check
+        }
+    }
+}
diff --git a/uids.control b/uids.control
index 34a516e..4fc9151 100644
--- a/uids.control
+++ b/uids.control
@@ -1,5 +1,5 @@
-comment = 'uids:  Created by pgx'
+comment = 'uids:  generate various types of unique identifiers'
 default_version = '@CARGO_VERSION@'
 module_pathname = '$libdir/uids'
 relocatable = false
-superuser = false
+superuser = true

From d47aa3531952795df05894e55dd4199e9a153101 Mon Sep 17 00:00:00 2001
From: Spark <79936503+spa5k@users.noreply.github.com>
Date: Sat, 8 Jun 2024 10:23:33 +0530
Subject: [PATCH 2/4] removing useless stuff

---
 .../workflows/build-and-test-gnu/action.yaml  | 231 ------------------
 .github/workflows/build-rpm/action.yaml       |  93 -------
 .github/workflows/container.yaml              |  65 -----
 .github/workflows/release.yaml                | 102 --------
 .github/workflows/test.yaml                   |  26 --
 .../base-pkg-alpine3.18-amd64.Dockerfile      |  55 -----
 infra/docker/builder-gnu.Dockerfile           |  77 ------
 ...ostgres-pg15.7-alpine3.18-amd64.Dockerfile |  45 ----
 ...ostgres-pg16.3-alpine3.18-amd64.Dockerfile |  45 ----
 9 files changed, 739 deletions(-)
 delete mode 100644 .github/workflows/build-and-test-gnu/action.yaml
 delete mode 100644 .github/workflows/build-rpm/action.yaml
 delete mode 100644 .github/workflows/container.yaml
 delete mode 100644 .github/workflows/release.yaml
 delete mode 100644 .github/workflows/test.yaml
 delete mode 100644 infra/docker/base-pkg-alpine3.18-amd64.Dockerfile
 delete mode 100644 infra/docker/builder-gnu.Dockerfile
 delete mode 100644 infra/docker/uids_postgres-pg15.7-alpine3.18-amd64.Dockerfile
 delete mode 100644 infra/docker/uids_postgres-pg16.3-alpine3.18-amd64.Dockerfile

diff --git a/.github/workflows/build-and-test-gnu/action.yaml b/.github/workflows/build-and-test-gnu/action.yaml
deleted file mode 100644
index f7eafc4..0000000
--- a/.github/workflows/build-and-test-gnu/action.yaml
+++ /dev/null
@@ -1,231 +0,0 @@
-name: build-and-test
-description: Build and test pg_idkit (meant to run inside pg_idkit/builder container)
-inputs:
-  artifact-upload:
-    type: boolean
-    default: false
-    description: |
-      Desired artifact name (will replace the natural name)
-  artifact-tarball-suffix:
-    type: string
-    default: "gnu"
-    description: |
-      Suffix that will be used on the tarball artifact (ex. '-gnu')
-  rust-container-version:
-    type: string
-    default: 1.76
-    description: |
-      Version of rust to use in the container
-  apt-cache-dir:
-    type: string
-    default: /var/cache/apt
-  cargo-home-dir:
-    type: string
-    default: /usr/local/cargo
-  cargo-target-dir:
-    type: string
-    default: /usr/local/build/target
-  sccache-dir:
-    type: string
-    default: /usr/local/sccache
-  cargo-build-rustc-wrapper:
-    type: string
-    default: /usr/local/cargo/bin/sccache
-  cargo-env-incremental:
-    type: string
-    default: "0"
-  cargo-env-profile:
-    type: string
-    default: ci
-  user:
-    type: string
-    default: idkit
-  pgrx-pg-version:
-    type: string
-    default: pg16
-    decription: |
-      PGRX version (ex. 'pg15', 'pg16')
-  pg-version:
-    type: string
-    default: 16.2
-    decription: |
-      Postgres version (ex. '15.6, '16.2')
-outputs: {}
-runs:
-  using: "composite"
-  steps:
-    # Checkout the repo
-    - uses: actions/checkout@v3
-
-    #########
-    # Cache #
-    #########
-
-    - name: Cache CARGO_HOME
-      uses: actions/cache@v3
-      continue-on-error: false
-      with:
-        path: |
-          ${{ inputs.cargo-home-dir }}
-        key: pg_idkit-tests-rust-${{ inputs.rust-container-version }}-cargo-${{ runner.os }}
-
-    - name: Cache apt install
-      uses: actions/cache@v3
-      continue-on-error: false
-      with:
-        path: |
-          ${{ inputs.apt-cache-dir }}
-        key: pg_idkit-tests-apt-cache-${{ inputs.rust-container-version }}-cargo-${{ runner.os }}
-
-    - name: Cache sccache
-      uses: actions/cache@v3
-      continue-on-error: false
-      with:
-        path: |
-          ${{ inputs.sccache-dir }}
-        key: pg_idkit-tests-sccache-${{ inputs.rust-container-version }}-cargo-${{ runner.os }}
-
-    - name: Cache pgrx init
-      uses: actions/cache@v3
-      continue-on-error: false
-      with:
-        path: |
-          /home/${{ inputs.user }}/.pgrx
-        key: pg_idkit-tests-pgrx-init-${{ inputs.rust-container-version }}-cargo-${{ runner.os }}
-
-    #########
-    # Setup #
-    #########
-
-    - name: Add idkit to group
-      shell: bash
-      run: |
-        chgrp -R idkit $HOME &&
-        chgrp -R idkit /__w/pg_idkit &&
-        chmod g+w -R /__w/pg_idkit
-
-    # Add directory used by worker as safe dir for git
-    - name: Add git safe dir
-      shell: bash
-      run: |
-        git config --global --add safe.directory /__w/pg_idkit/pg_idkit
-        su idkit -c "git config --global --add safe.directory /__w/pg_idkit/pg_idkit"
-
-
-    - name: Reinstall deps due to GLIBC issue
-      if: ${{ inputs.artifact-upload }}
-      shell: bash
-      env:
-        CARGO_BUILD_RUSTC_WRAPPER: ${{ inputs.cargo-build-rustc-wrapper }}
-        CARGO_HOME: ${{ inputs.cargo-home-dir }}
-        CARGO_INCREMENTAL: ${{ inputs.cargo-env-incrmental }}
-        CARGO_PROFILE: ${{ inputs.cargo-profile }}
-        CARGO_TARGET_DIR: ${{ inputs.cargo-target-dir }}
-        PGRX_PG_VERSION: ${{ inputs.pgrx-pg-version }}
-        PGRX_PKG_PATH_PREFIX: ${{ inputs.cargo-target-dir }}
-        PKG_PG_VERSION: ${{ inputs.pg-version }}
-        SCCACHE_DIR: ${{ inputs.sccache-dir }}
-        DOCKER_BUILD_USER: ${{ inputs.user }}
-      run: |
-        su idkit -c "cargo install --locked --force cargo-get cargo-edit"
-
-    ###############
-    # Build/Tests #
-    ###############
-
-    # Initialize cargo-pgrx if necessary
-    - name: Initialize cargo-pgrx
-      shell: bash
-      env:
-        CARGO_BUILD_RUSTC_WRAPPER: ${{ inputs.cargo-build-rustc-wrapper }}
-        CARGO_HOME: ${{ inputs.cargo-home-dir }}
-        CARGO_INCREMENTAL: ${{ inputs.cargo-env-incrmental }}
-        CARGO_PROFILE: ${{ inputs.cargo-profile }}
-        CARGO_TARGET_DIR: ${{ inputs.cargo-target-dir }}
-        PGRX_PG_VERSION: ${{ inputs.pgrx-pg-version }}
-        PGRX_PKG_PATH_PREFIX: ${{ inputs.cargo-target-dir }}
-        PKG_PG_VERSION: ${{ inputs.pg-version }}
-        SCCACHE_DIR: ${{ inputs.sccache-dir }}
-        DOCKER_BUILD_USER: ${{ inputs.user }}
-      run: |
-        su idkit -c "just pgrx-init"
-
-    # Run cargo check
-    - name: Run cargo check
-      shell: bash
-      env:
-        CARGO_BUILD_RUSTC_WRAPPER: ${{ inputs.cargo-build-rustc-wrapper }}
-        CARGO_HOME: ${{ inputs.cargo-home-dir }}
-        CARGO_INCREMENTAL: ${{ inputs.cargo-env-incrmental }}
-        CARGO_PROFILE: ${{ inputs.cargo-profile }}
-        CARGO_TARGET_DIR: ${{ inputs.cargo-target-dir }}
-        PGRX_PG_VERSION: ${{ inputs.pgrx-pg-version }}
-        PGRX_PKG_PATH_PREFIX: ${{ inputs.cargo-target-dir }}
-        PKG_PG_VERSION: ${{ inputs.pg-version }}
-        SCCACHE_DIR: ${{ inputs.sccache-dir }}
-        DOCKER_BUILD_USER: ${{ inputs.user }}
-      run: |
-        su idkit -c "cargo check"
-
-    # Run cargo build
-    - name: Run cargo test
-      shell: bash
-      env:
-        CARGO_BUILD_RUSTC_WRAPPER: ${{ inputs.cargo-build-rustc-wrapper }}
-        CARGO_HOME: ${{ inputs.cargo-home-dir }}
-        CARGO_INCREMENTAL: ${{ inputs.cargo-env-incrmental }}
-        CARGO_PROFILE: ${{ inputs.cargo-profile }}
-        CARGO_TARGET_DIR: ${{ inputs.cargo-target-dir }}
-        PGRX_PG_VERSION: ${{ inputs.pgrx-pg-version }}
-        PGRX_PKG_PATH_PREFIX: ${{ inputs.cargo-target-dir }}
-        PKG_PG_VERSION: ${{ inputs.pg-version }}
-        SCCACHE_DIR: ${{ inputs.sccache-dir }}
-        DOCKER_BUILD_USER: ${{ inputs.user }}
-      run: |
-        su idkit -c "cargo build"
-
-    # Run cargo test
-    - name: Run cargo test
-      shell: bash
-      env:
-        CARGO_BUILD_RUSTC_WRAPPER: ${{ inputs.cargo-build-rustc-wrapper }}
-        CARGO_HOME: ${{ inputs.cargo-home-dir }}
-        CARGO_INCREMENTAL: ${{ inputs.cargo-env-incrmental }}
-        CARGO_PROFILE: ${{ inputs.cargo-profile }}
-        CARGO_TARGET_DIR: ${{ inputs.cargo-target-dir }}
-        PGRX_PG_VERSION: ${{ inputs.pgrx-pg-version }}
-        PKG_PG_VERSION: ${{ inputs.pg-version }}
-        SCCACHE_DIR: ${{ inputs.sccache-dir }}
-        DOCKER_BUILD_USER: ${{ inputs.user }}
-      run: |
-        su idkit -c "cargo test"
-
-    #############
-    # Artifacts #
-    #############
-
-    # Run cargo test
-    - name: Build a package
-      if: ${{ inputs.artifact-upload }}
-      shell: bash
-      env:
-        CARGO_BUILD_RUSTC_WRAPPER: ${{ inputs.cargo-build-rustc-wrapper }}
-        CARGO_HOME: ${{ inputs.cargo-home-dir }}
-        CARGO_INCREMENTAL: ${{ inputs.cargo-env-incrmental }}
-        CARGO_PROFILE: ${{ inputs.cargo-profile }}
-        CARGO_TARGET_DIR: ${{ inputs.cargo-target-dir }}
-        PGRX_PG_VERSION: ${{ inputs.pgrx-pg-version }}
-        PGRX_PKG_PATH_PREFIX: ${{ inputs.cargo-target-dir }}
-        PKG_PG_VERSION: ${{ inputs.pg-version }}
-        PKG_TARBALL_SUFFIX: ${{ inputs.artifact-tarball-suffix }}
-        SCCACHE_DIR: ${{ inputs.sccache-dir }}
-        DOCKER_BUILD_USER: ${{ inputs.user }}
-      run: |
-        su idkit -c "just package"
-
-    # Upload artifact
-    - name: Upload artifact
-      if: ${{ inputs.artifact-upload }}
-      uses: actions/upload-artifact@v3
-      with:
-        path: pg_idkit-*.tar.gz
\ No newline at end of file
diff --git a/.github/workflows/build-rpm/action.yaml b/.github/workflows/build-rpm/action.yaml
deleted file mode 100644
index 8e46d77..0000000
--- a/.github/workflows/build-rpm/action.yaml
+++ /dev/null
@@ -1,93 +0,0 @@
-name: build-rpm
-description: Build an RPM for pg_idkit
-inputs:
-  artifact-upload:
-    type: boolean
-    description: |
-      Whether to upload an artifact or not
-  artifact-name:
-    type: string
-    description: |
-      Desired artifact name (will replace the natural name)
-  gh-runner:
-    type: string
-    default: ubuntu-latest
-    decription: |
-      GitHub runner to use
-  rpm-arch:
-    type: string
-    default: x86_64
-    decription: |
-      Architecture to use while building the RPM
-  pgrx-pg-version:
-    type: string
-    default: pg16
-    decription: |
-      PGRX version (ex. 'pg15', 'pg16')
-  pg-version:
-    type: string
-    default: 16.2
-    decription: |
-      Postgres version (ex. '15.6, '16.2')
-  cargo-pgrx-version:
-    type: string
-    default: 0.11.3
-    decription: |
-      cargo-pgrx version (ex. '0.11.3')
-  user:
-    type: string
-    default: runner
-outputs: {}
-runs:
-  using: "composite"
-  steps:
-    - uses: actions/checkout@v3
-
-    - uses: Swatinem/rust-cache@v2
-
-    - name: Cache default PGRX_HOME
-      uses: actions/cache@v3
-      continue-on-error: false
-      with:
-        path: |
-          /home/runner/.pgrx
-        key: pg_idkit-pkg-rpm-pgrx-${{ inputs.rpm-arch }}-${{ inputs.gh-runner }}
-
-    - name: Install Rust deps
-      uses: taiki-e/install-action@v2
-      with:
-        tool: cargo-get,just,cargo-generate-rpm,cargo-pgrx@${{ inputs.cargo-pgrx-version }}
-
-    - name: Initialize cargo-pgrx
-      shell: bash
-      env:
-        PGRX_PG_VERSION: ${{ inputs.pgrx-pg-version }}
-        PKG_PG_VERSION: ${{ inputs.pg-version }}
-      run: |
-        [[ -d /home/runner/.pgrx ]] || cargo pgrx init
-
-    - name: Build RPM
-      shell: bash
-      env:
-        DOCKER_BUILD_USER: ${{ inputs.user }}
-        PGRX_PG_VERSION: ${{ inputs.pgrx-pg-version }}
-        PKG_PG_VERSION: ${{ inputs.pg-version }}
-      run: just package build-rpm
-
-    - name: Get RPM output path
-      id: rpm-output
-      shell: bash
-      env:
-        DOCKER_BUILD_USER: ${{ inputs.user }}
-        PGRX_PG_VERSION: ${{ inputs.pgrx-pg-version }}
-        PKG_PG_VERSION: ${{ inputs.pg-version }}
-      run: |
-        echo path=$(just print-rpm-output-path) >> $GITHUB_OUTPUT
-        echo filename=$(just print-rpm-output-file-name) >> $GITHUB_OUTPUT
-
-    - name: Upload artifact
-      if: ${{ inputs.artifact-upload }}
-      uses: actions/upload-artifact@v3
-      with:
-        name: ${{ steps.rpm-output.outputs.filename }}
-        path: ${{ steps.rpm-output.outputs.path }}
\ No newline at end of file
diff --git a/.github/workflows/container.yaml b/.github/workflows/container.yaml
deleted file mode 100644
index b38b676..0000000
--- a/.github/workflows/container.yaml
+++ /dev/null
@@ -1,65 +0,0 @@
-name: container
-
-on:
-  push:
-    branches:
-      # Run on auto-generated release PRs
-      - prep-release-v[0-9]+\.[0-9]+\.[0-9]+
-    tags:
-      - v[0-9]+\.[0-9]+\.[0-9]+
-
-jobs:
-  build:
-    permissions:
-      contents: read
-      packages: write
-    runs-on: ${{ matrix.config.gh.runner }}
-    strategy:
-      matrix:
-        config:
-          - triple: x86_64-unknown-linux-musl
-            gh:
-              runner: ubuntu-22.04
-            container:
-              arch: amd64
-              pg_version: 15.6
-              os_version: alpine3.18
-          - triple: x86_64-unknown-linux-musl
-            gh:
-              runner: ubuntu-22.04
-            container:
-              arch: amd64
-              pg_version: 16.2
-              os_version: alpine3.18
-    steps:
-      - uses: actions/checkout@v3
-      - uses: docker/setup-qemu-action@v3
-      - uses: taiki-e/install-action@v2
-        with:
-          tool: cargo-get,just
-
-      - name: Registry login
-        uses: docker/login-action@v3
-        with:
-          registry: ghcr.io
-          username: ${{ github.actor }}
-          password: ${{ secrets.GITHUB_TOKEN }}
-
-      - name: Build container image (prerelease)
-        if: ${{ startsWith(github.ref, 'refs/heads/prep-release') }}
-        run: just build-image push-image
-        env:
-          CONTAINER_IMAGE_ARCH: ${{ matrix.config.container.arch }}
-          PGRX_PG_VERSION: ${{ matrix.config.container.pg_version }}
-          POSTGRES_IMAGE_VERSION: ${{ matrix.config.container.pg_version }}
-          POSTGRES_OS_IMAGE_VERSION: ${{ matrix.config.container.os_version }}
-          PGIDKIT_IMAGE_TAG_SUFFIX: "-prerelease"
-
-      - name: Build container image
-        if: ${{ startsWith(github.ref, 'refs/tags/v') }}
-        run: just build-image push-image
-        env:
-          CONTAINER_IMAGE_ARCH: ${{ matrix.config.container.arch }}
-          PGRX_PG_VERSION: ${{ matrix.config.container.pg_version }}
-          POSTGRES_IMAGE_VERSION: ${{ matrix.config.container.pg_version }}
-          POSTGRES_OS_IMAGE_VERSION: ${{ matrix.config.container.os_version }}
\ No newline at end of file
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
deleted file mode 100644
index 689f1ba..0000000
--- a/.github/workflows/release.yaml
+++ /dev/null
@@ -1,102 +0,0 @@
-name: release
-
-on:
-  workflow_dispatch:
-    inputs:
-      version:
-        description: Version to release (ex. `0.1.0`)
-        required: false
-        type: string
-
-  push:
-    branches:
-      # Run on all commits to main, because GitHub somehow doesn't support only specifying tag patterns
-      # (filtering must be done at the per-job level with an `if`)
-      - main
-      # Run on auto-generated release PRs
-      - prep-release-v[0-9]+\.[0-9]+\.[0-9]+
-    tags:
-      # Run on released tags (created by automated post-merge release-tagging), to generate the actual release
-      - v[0-9]+\.[0-9]+\.[0-9]+
-
-jobs:
-  build-rpm:
-    runs-on: ubuntu-latest
-    if: ${{ startsWith(github.ref, 'refs/tags/v') || startsWith(github.ref, 'refs/tags/prep-release-v')  }}
-    strategy:
-      matrix:
-        config:
-          - pgrx:
-              pg-version: pg15
-            pg:
-              version: 15.6
-          - pgrx:
-              pg-version: pg16
-            pg:
-              version: 16.2
-    steps:
-      - uses: actions/checkout@v3
-
-      - name: Build the RPM (reuse workflow)
-        uses: ./.github/workflows/build-rpm
-        with:
-          artifact-upload: true
-          pgrx-pg-version: ${{ matrix.config.pgrx.pg-version }}
-          pg-version: ${{ matrix.config.pg.version }}
-
-  build-zip-gnu:
-    runs-on: ubuntu-latest
-    if: ${{ startsWith(github.ref, 'refs/tags/v') || startsWith(github.ref, 'refs/tags/prep-release-v')  }}
-    container:
-      image: ghcr.io/spa5k/uids-postgres/builder-gnu:0.1.x
-    strategy:
-      matrix:
-        config:
-          - pgrx:
-              pg-version: pg15
-            pg:
-              version: 15.6
-          - pgrx:
-              pg-version: pg16
-            pg:
-              version: 16.2
-    steps:
-      - uses: actions/checkout@v3
-
-      - name: Build the package (reuse workflow)
-        uses: ./.github/workflows/build-and-test-gnu
-        with:
-          artifact-upload: true
-          artifact-tarball-suffix: "-${{ matrix.config.pgrx.pg-version }}-gnu"
-          pgrx-pg-version: ${{ matrix.config.pgrx.pg-version }}
-          pg-version: ${{ matrix.config.pg.version }}
-
-  release:
-    runs-on: ubuntu-latest
-    if: ${{ startsWith(github.ref, 'refs/tags/v') || startsWith(github.ref, 'refs/tags/prep-release-v')  }}
-    permissions:
-      contents: write
-    needs:
-      - build-rpm
-      - build-zip-gnu
-    steps:
-      # Checkout the repository
-      - uses: actions/checkout@v3
-
-      # Download all artifacts
-      - uses: actions/download-artifact@v3
-        with:
-          path: artifacts
-
-      # Create release (pre-release if we're prepping)
-      - name: Create release
-        uses: softprops/action-gh-release@v1
-        with:
-          prerelease: ${{ startsWith(github.ref, 'refs/heads/prep-release') }}
-          draft: ${{ startsWith(github.ref, 'refs/heads/prep-release') }}
-          tag_name: ${{ github.ref || inputs.version }}
-          # NOTE: while we have the CHANGELOG file, it always contains *all* changes,
-          # so we will use the generated GitHub commits for now
-          generate_release_notes: true
-          files: |
-            ./artifacts/*/*
\ No newline at end of file
diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml
deleted file mode 100644
index c5d2249..0000000
--- a/.github/workflows/test.yaml
+++ /dev/null
@@ -1,26 +0,0 @@
-name: test
-
-on:
-  push:
-
-jobs:
-  test:
-    runs-on: ubuntu-latest
-    container:
-      image: ghcr.io/spa5k/uids-postgres/builder-gnu:0.1.x
-    strategy:
-      matrix:
-        config:
-        - rpm:
-            arch: x86_64
-          pgrx:
-            version: pg15
-        - rpm:
-            arch: x86_64
-          pgrx:
-            version: pg16
-    steps:
-      - uses: actions/checkout@v3
-
-      - name: Build & test the project
-        uses: ./.github/workflows/build-and-test-gnu
\ No newline at end of file
diff --git a/infra/docker/base-pkg-alpine3.18-amd64.Dockerfile b/infra/docker/base-pkg-alpine3.18-amd64.Dockerfile
deleted file mode 100644
index a442142..0000000
--- a/infra/docker/base-pkg-alpine3.18-amd64.Dockerfile
+++ /dev/null
@@ -1,55 +0,0 @@
-FROM alpine:latest AS builder
-
-# Allow for overriding rust toolcahin version
-ARG RUST_TOOLCHAIN_VERSION=1.76
-ENV RUST_TOOLCHAIN_VERSION=$RUST_TOOLCHAIN_VERSION
-
-# Allow for overriding of PGRX PG version that is used
-ARG PGRX_PG_VERSION=pg16
-ENV PGRX_PG_VERSION=$PGRX_PG_VERSION
-
-# Allow overriding features so that this file can be used to build
-# different crate features. By default since this is a 16.2 base package
-# we expect to build with crate feature 'pg16'
-ARG CARGO_FEATURES=pg16
-ENV CARGO_FEATURES=$CARGO_FEATURES
-
-# Install OS deps
-RUN apk add --no-cache \
-    alpine-sdk \
-    bash \
-    bison \
-    clang \
-    clang-dev \
-    clang-libs \
-    coreutils \
-    flex \
-    icu-dev \
-    linux-headers \
-    musl-dev \
-    openssl-dev \
-    perl \
-    readline \
-    readline-dev \
-    rustup \
-    zlib-dev
-
-# Install Rust & related deps
-RUN rustup-init -y --profile minimal --default-toolchain $RUST_TOOLCHAIN_VERSION
-ENV PATH="/root/.cargo/bin:${PATH}"
-RUN cargo install just cargo-get
-
-# Install pgrx
-# (disabling the static C runtime is required since pgrx requires dynamic linking w/ libssl and libcrypto)
-RUN RUSTFLAGS="-Ctarget-feature=-crt-static" cargo install --locked cargo-pgrx@0.11.4
-
-# Copy in uids code
-WORKDIR /uids
-COPY . .
-
-# Initialize pgrx
-ENV PGRX_IGNORE_RUST_VERSIONS=y
-RUN just pgrx-init
-
-# Build the package
-RUN RUSTFLAGS="-Ctarget-feature=-crt-static" just build package
\ No newline at end of file
diff --git a/infra/docker/builder-gnu.Dockerfile b/infra/docker/builder-gnu.Dockerfile
deleted file mode 100644
index 97df053..0000000
--- a/infra/docker/builder-gnu.Dockerfile
+++ /dev/null
@@ -1,77 +0,0 @@
-# rust:1.76.0-slim-bullseye as of 2024/03/06
-FROM rust:1.76.0-slim-bullseye
-
-ENV CARGO_HOME=/usr/local/cargo
-ENV CARGO_TARGET_DIR=/usr/local/build/target
-ENV SCCACHE_DIR=/usr/local/sccache
-# Disable cargo incremental builds since sccache can't support them
-ENV CARGO_INCREMENTAL=0
-
-# Install deps
-RUN apt update && apt install -y libssl-dev git openssh-client pkg-config curl ca-certificates gnupg wget
-RUN cargo install sccache --locked
-
-ENV CARGO_BUILD_RUSTC_WRAPPER=/usr/local/cargo/bin/sccache
-
-##################
-# Setup Postgres #
-##################
-
-# Add postgresql.org PGP keys
-RUN wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add
-
-# Add postgres repo
-RUN sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt bullseye-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
-
-# Install pg15
-RUN apt -y update && apt -y upgrade && apt install -y postgresql-15
-
-# Install NodeJS
-RUN set -uex; \
-    apt-get update; \
-    apt-get install -y ca-certificates curl gnupg; \
-    mkdir -p /etc/apt/keyrings; \
-    curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key \
-     | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg; \
-    NODE_MAJOR=20; \
-    echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" \
-     > /etc/apt/sources.list.d/nodesource.list; \
-    apt-get update; \
-    apt-get install nodejs -y;
-
-# Install dependencies for building postgres, NodeJS, etc
-RUN apt-get update && \
-    apt-get install -y --no-install-recommends ca-certificates \
-    git build-essential libpq-dev \
-    postgresql postgresql-server-dev-15 \
-    curl libreadline6-dev zlib1g-dev libclang-dev \
-    pkg-config cmake nodejs
-
-# Add postgres user to root group
-RUN useradd --user-group --system --create-home --no-log-init uids && \
-    usermod -aG sudo uids && \
-    chown -R uids /home/uids && \
-    addgroup uids root
-
-# Allow writing to postgres extensions folder
-RUN chmod g+w -R /usr/share/postgresql/**/extension && \
-    chmod g+w -R /usr/lib/postgresql/**/lib
-
-###############
-# Setup Cargo #
-###############
-
-# Allow writing to cargo cache by uids (now part of root group)
-RUN chmod g+w -R /usr/local/cargo
-RUN chmod g+w -R /usr/local/build
-
-RUN mkdir /usr/local/sccache
-RUN chmod g+w -R /usr/local/sccache
-
-# Install & Initialize pgrx
-# NOTE: pgrx must be reinitialized if cargo-pgrx changes
-RUN su uids -c "cargo install cargo-pgrx@0.11.4"
-RUN su uids -c "cargo pgrx init --pg15 download"
-
-# Install development/build/testing deps
-RUN su uids -c "cargo install just sccache cargo-cache cargo-get cargo-edit"
\ No newline at end of file
diff --git a/infra/docker/uids_postgres-pg15.7-alpine3.18-amd64.Dockerfile b/infra/docker/uids_postgres-pg15.7-alpine3.18-amd64.Dockerfile
deleted file mode 100644
index b1d1f16..0000000
--- a/infra/docker/uids_postgres-pg15.7-alpine3.18-amd64.Dockerfile
+++ /dev/null
@@ -1,45 +0,0 @@
-#
-# NOTE: you must have the base packaging layer built for this image to work
-# you can build this from scratch with `just build-base-pkg-image`
-#
-# `cargo pgrx init` is run in the base-pkg, so it contains the versions of pg that will be used.
-#
-FROM ghcr.io/spa5k/uids-postgres/base-pkg:0.1.x-alpine3.18-amd64 AS builder
-
-ARG USER
-ENV USER=$USER
-
-ARG PGRX_PG_VERSION=pg15
-ENV PGRX_PG_VERSION=$PGRX_PG_VERSION
-
-ARG PKG_PG_VERSION=15.7
-ENV PKG_PG_VERSION=$PKG_PG_VERSION
-
-ENV PKG_TARBALL_SUFFIX="-musl"
-
-# Re-run the build with the latest code
-WORKDIR /uids
-COPY . .
-RUN RUSTFLAGS="-Ctarget-feature=-crt-static" just build package
-
-FROM postgres:15.7-alpine3.18
-
-# NOTE: PGRX_PG_VERSION is defined via base-pkg:pg15.5-alpine3.18-amd64
-ARG PGRX_PG_VERSION=pg15
-ARG PGIDKIT_VERSION
-ARG PGIDKIT_REVISION
-
-# Install packaged uids for system postgres
-COPY --from=builder /uids/uids-*-musl.tar.gz /tmp
-RUN tar -C /usr/local --strip-components=1 -xvf /tmp/uids-*-musl.tar.gz
-
-LABEL org.opencontainers.image.authors="spa5k"
-LABEL org.opencontainers.image.description="A distribution of the base postgres image, with uids pre-installed."
-LABEL org.opencontainers.image.documentation="https://github.com/spa5k/uids-postgres#readme"
-LABEL org.opencontainers.image.licenses="Apache-2.0"
-LABEL org.opencontainers.image.revision=$PGIDKIT_REVISION
-LABEL org.opencontainers.image.source="https://github.com/spa5k/uids-postgres"
-LABEL org.opencontainers.image.title="Postgres + uids"
-LABEL org.opencontainers.image.url="https://github.com/spa5k/uids-postgres"
-LABEL org.opencontainers.image.vendor="spa5k"
-LABEL org.opencontainers.image.version=v${PGIDKIT_VERSION}
\ No newline at end of file
diff --git a/infra/docker/uids_postgres-pg16.3-alpine3.18-amd64.Dockerfile b/infra/docker/uids_postgres-pg16.3-alpine3.18-amd64.Dockerfile
deleted file mode 100644
index 945cb61..0000000
--- a/infra/docker/uids_postgres-pg16.3-alpine3.18-amd64.Dockerfile
+++ /dev/null
@@ -1,45 +0,0 @@
-#
-# NOTE: you must have the base packaging layer built for this image to work
-# you can build this from scratch with `just build-base-pkg-image`
-#
-# `cargo pgrx init` is run in the base-pkg, so it contains the versions of pg that will be used.
-#
-FROM ghcr.io/spa5k/uids-postgres/base-pkg:0.1.x-alpine3.18-amd64 AS builder
-
-ARG USER
-ENV USER=$USER
-
-ARG PGRX_PG_VERSION=pg16
-ENV PGRX_PG_VERSION=$PGRX_PG_VERSION
-
-ARG PKG_PG_VERSION=16.3
-ENV PKG_PG_VERSION=$PKG_PG_VERSION
-
-ENV PKG_TARBALL_SUFFIX="-musl"
-
-# Re-run the build with the latest code
-WORKDIR /uids
-COPY . .
-RUN RUSTFLAGS="-Ctarget-feature=-crt-static" just build package
-
-FROM postgres:16-alpine
-
-# NOTE: PGRX_PG_VERSION is defined via base-pkg:pg16.5-alpine3.18-amd64
-ARG PGRX_PG_VERSION=pg16
-ARG PGIDKIT_VERSION
-ARG PGIDKIT_REVISION
-
-# Install packaged uids for system postgres
-COPY --from=builder /uids/uids-*-musl.tar.gz /tmp
-RUN tar -C /usr/local --strip-components=1 -xvf /tmp/uids-*-musl.tar.gz
-
-LABEL org.opencontainers.image.authors="spa5k"
-LABEL org.opencontainers.image.description="A distribution of the base postgres image, with uids pre-installed."
-LABEL org.opencontainers.image.documentation="https://github.com/spa5k/uids-postgres#readme"
-LABEL org.opencontainers.image.licenses="Apache-2.0"
-LABEL org.opencontainers.image.revision=$PGIDKIT_REVISION
-LABEL org.opencontainers.image.source="https://github.com/spa5k/uids-postgres"
-LABEL org.opencontainers.image.title="Postgres + uids"
-LABEL org.opencontainers.image.url="https://github.com/spa5k/uids-postgres"
-LABEL org.opencontainers.image.vendor="spa5k"
-LABEL org.opencontainers.image.version=v${PGIDKIT_VERSION}
\ No newline at end of file

From 5975c4ab9ce50f752e65a1796b24939f34a20d48 Mon Sep 17 00:00:00 2001
From: Spark <79936503+spa5k@users.noreply.github.com>
Date: Sat, 8 Jun 2024 10:26:30 +0530
Subject: [PATCH 3/4] adding cicd

---
 .dockerignore                 |   8 +++
 .github/workflows/ci.yml      |  58 ++++++++++++++++
 .github/workflows/release.yml | 120 ++++++++++++++++++++++++++++++++++
 Dockerfile                    |  51 +++++++++++++++
 4 files changed, 237 insertions(+)
 create mode 100644 .dockerignore
 create mode 100644 .github/workflows/ci.yml
 create mode 100644 .github/workflows/release.yml
 create mode 100644 Dockerfile

diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..b4efeae
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,8 @@
+.git
+.github
+.gitignore
+*.md
+*.yml
+
+target
+Cargo.lock
\ No newline at end of file
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..80a74a3
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,58 @@
+name: CI
+on:
+  pull_request:
+    branches: [master]
+    types: [opened, reopened, synchronize]
+concurrency:
+  group: ${{ github.workflow }}-${{ github.ref }}
+  cancel-in-progress: true
+jobs:
+  ci:
+    name: CI
+    needs: [test, lint, lockfile]
+    runs-on: ubuntu-latest
+    steps:
+      - name: Done
+        run: exit 0
+  test:
+    name: Tests
+    strategy:
+      fail-fast: false
+      matrix:
+        postgres: [14, 15, 16]
+        runner:
+          - ubuntu-22.04
+          - buildjet-8vcpu-ubuntu-2204-arm
+    runs-on: ${{ matrix.runner }}
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v3
+      - name: Build
+        run: docker buildx build --build-arg PG_MAJOR=${{ matrix.postgres }} -t test .
+      - name: Test
+        run: docker run test cargo pgrx test pg${{ matrix.postgres }}
+  lint:
+    name: Linting (fmt + clippy)
+    runs-on: ubuntu-latest
+    steps:
+      - name: Install rust
+        uses: dtolnay/rust-toolchain@1.74.0
+        with:
+          components: rustfmt, clippy
+      - name: Checkout
+        uses: actions/checkout@v3
+      - name: Format check
+        uses: actions-rs/cargo@v1
+        with:
+          command: fmt
+          args: -- --check
+
+  lockfile:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v3
+      - name: Install rust
+        uses: dtolnay/rust-toolchain@1.74.0
+      - name: Lockfile check
+        run: cargo update -w --locked
\ No newline at end of file
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 0000000..57db33c
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,120 @@
+env:
+  NAME: uids_postgres
+  EXT_NAME: ulid
+  PKG_NAME: uids_postgres
+name: Release
+on:
+  push:
+    tags: [v*]
+concurrency:
+  group: ${{ github.workflow }}-${{ github.ref }}
+jobs:
+  create-release:
+    name: Create release
+    runs-on: ubuntu-latest
+    outputs:
+      upload_url: ${{ steps.create-release.outputs.upload_url }}
+    steps:
+      - name: Create Release
+        id: create-release
+        uses: actions/create-release@v1
+        env:
+          GITHUB_TOKEN: ${{ github.token }}
+        with:
+          tag_name: ${{ github.ref }}
+          release_name: ${{ github.ref }}
+  build-linux-gnu:
+    name: Build & Release for linux
+    needs:
+      - create-release
+    strategy:
+      fail-fast: false
+      matrix:
+        postgres: [14, 15, 16]
+        box:
+          - runner: ubuntu-22.04
+            arch: amd64
+          - runner: buildjet-8vcpu-ubuntu-2204-arm
+            arch: arm64
+    runs-on: ${{ matrix.box.runner }}
+    timeout-minutes: 45
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v3
+      - name: Install rust
+        uses: dtolnay/rust-toolchain@1.74.0
+      - name: Install dependencies
+        run: |
+          # Add postgres package repo
+          sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
+          wget -qO- https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo tee /etc/apt/trusted.gpg.d/pgdg.asc &>/dev/null
+
+          sudo apt-get update
+          sudo apt-get install -y --no-install-recommends git build-essential libpq-dev curl libreadline6-dev zlib1g-dev pkg-config cmake
+          sudo apt-get install -y --no-install-recommends libreadline-dev zlib1g-dev flex bison libxml2-dev libxslt-dev libssl-dev libxml2-utils xsltproc ccache
+          sudo apt-get install -y --no-install-recommends clang libclang-dev llvm-dev gcc tree
+
+          # Install requested postgres version
+          sudo apt-get install -y postgresql-${{ matrix.postgres }} postgresql-server-dev-${{ matrix.postgres }} -y
+
+          # Ensure installed pg_config is first on path
+          export PATH=$PATH:/usr/lib/postgresql/${{ matrix.postgres }}/bin
+
+          cargo install cargo-pgrx --version 0.11.2 --locked
+          cargo pgrx init --pg${{ matrix.postgres }}=/usr/lib/postgresql/${{ matrix.postgres }}/bin/pg_config
+      - name: Build artifacts
+        run: |
+          # selects the pgVer from pg_config on path
+          # https://github.com/tcdi/pgrx/issues/288
+          cargo pgrx package --no-default-features --features pg${{ matrix.postgres }}
+
+          # Create installable package
+          mkdir archive
+          cp `find target/release -type f -name "${{ env.EXT_NAME }}*"` archive
+
+          # Copy files into directory structure
+          mkdir -p package/usr/lib/postgresql/lib
+          mkdir -p package/var/lib/postgresql/extension
+          cp archive/*.so package/usr/lib/postgresql/lib
+          cp archive/*.control package/var/lib/postgresql/extension
+          cp archive/*.sql package/var/lib/postgresql/extension
+
+          # symlinks to Copy files into directory structure
+          mkdir -p package/usr/lib/postgresql/${{ matrix.postgres }}/lib
+          cd package/usr/lib/postgresql/${{ matrix.postgres }}/lib
+          cp -s ../../lib/*.so .
+          cd ../../../../../..
+
+          mkdir -p package/usr/share/postgresql/${{ matrix.postgres }}/extension
+          cd package/usr/share/postgresql/${{ matrix.postgres }}/extension
+
+          cp -s ../../../../../var/lib/postgresql/extension/${{ env.EXT_NAME }}.control .
+          cp -s ../../../../../var/lib/postgresql/extension/${{ env.EXT_NAME }}*.sql .
+          cd ../../../../../..
+
+          # Create install control file
+          extension_version=${{ github.ref_name }}
+          # strip the leading v
+          deb_version=${extension_version:1}
+
+          mkdir -p package/DEBIAN
+          touch package/DEBIAN/control
+          echo 'Package: ${{ env.PKG_NAME }}' >> package/DEBIAN/control
+          echo 'Version:' ${deb_version} >> package/DEBIAN/control
+          echo 'Architecture: ${{ matrix.box.arch }}' >> package/DEBIAN/control
+          echo 'Maintainer: Pavan Sunkara' >> package/DEBIAN/control
+          echo 'Description: A PostgreSQL extension for ULID' >> package/DEBIAN/control
+
+          # Create deb package
+          sudo chown -R root:root package
+          sudo chmod -R 00755 package
+          sudo dpkg-deb -Zxz --build --root-owner-group package
+      - name: Upload artifacts
+        uses: actions/upload-release-asset@v1
+        env:
+          GITHUB_TOKEN: ${{ github.token }}
+        with:
+          upload_url: ${{ needs.create-release.outputs.upload_url }}
+          asset_path: ./package.deb
+          asset_name: ${{ env.NAME }}-${{ github.ref_name }}-pg${{ matrix.postgres }}-${{ matrix.box.arch }}-linux-gnu.deb
+          asset_content_type: application/vnd.debian.binary-package
\ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..b4b92de
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,51 @@
+ARG PG_MAJOR
+
+FROM postgres:${PG_MAJOR}
+
+RUN apt-get update
+
+ENV build_deps ca-certificates \
+  git \
+  build-essential \
+  libpq-dev \
+  postgresql-server-dev-${PG_MAJOR} \
+  curl \
+  libreadline6-dev \
+  zlib1g-dev
+
+RUN apt-get install -y --no-install-recommends $build_deps pkg-config cmake
+
+WORKDIR /home/postgres
+
+ENV HOME=/home/postgres
+ENV PATH=/home/postgres/.cargo/bin:$PATH
+
+RUN chown postgres:postgres /home/postgres
+
+USER postgres
+
+RUN \
+  curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --no-modify-path --profile minimal --default-toolchain 1.74.0 && \
+  rustup --version && \
+  rustc --version && \
+  cargo --version
+
+# pgrx
+RUN cargo install cargo-pgrx --version 0.11.2 --locked
+
+RUN cargo pgrx init --pg${PG_MAJOR} $(which pg_config)
+
+USER root
+
+COPY . .
+
+RUN cargo pgrx install
+
+RUN chown -R postgres:postgres /home/postgres
+RUN chown -R postgres:postgres /usr/share/postgresql/${PG_MAJOR}/extension
+RUN chown -R postgres:postgres /usr/lib/postgresql/${PG_MAJOR}/lib
+
+USER postgres
+
+ENV POSTGRES_HOST_AUTH_METHOD=trust
+ENV USER=postgres
\ No newline at end of file

From bc8a84a17bf7a8b2ecb630d54d382c504afb924f Mon Sep 17 00:00:00 2001
From: Spark <79936503+spa5k@users.noreply.github.com>
Date: Sat, 8 Jun 2024 10:28:27 +0530
Subject: [PATCH 4/4] adding main branch

---
 .github/workflows/ci.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 80a74a3..512dce1 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -1,7 +1,7 @@
 name: CI
 on:
   pull_request:
-    branches: [master]
+    branches: [main, rewrite]
     types: [opened, reopened, synchronize]
 concurrency:
   group: ${{ github.workflow }}-${{ github.ref }}