Skip to content

Instantly share code, notes, and snippets.

@MendyLanda
Created September 8, 2024 03:37
Show Gist options
  • Save MendyLanda/c865d891947be1be08f3291767f49e97 to your computer and use it in GitHub Desktop.
Save MendyLanda/c865d891947be1be08f3291767f49e97 to your computer and use it in GitHub Desktop.
// P.S. the real moeny is at the buttom of the file
import { getTableColumns, type Table } from "drizzle-orm";
/**
* Creates a column selector for a given Drizzle ORM table.
*
* This function allows for flexible selection and omission of columns from a table.
*
* @param table - The Drizzle ORM table to create a column selector for.
* @returns A column selector object that can be used to select and omit columns from the table, access the result with `.columns`
*
* @example
* // Assuming we have a 'users' table with columns: id, name, email, age
* const userSelector = columnSelector(usersTable);
*
* // Select specific columns
* const nameAndEmail = userSelector.select('name', 'email').columns;
* // Result: { name: Column, email: Column }
*
* // Omit specific columns
* const withoutAge = userSelector.omit('age').columns;
* // Result: { id: Column, name: Column, email: Column }
*
* // Chain operations
* const onlyName = userSelector.select('name', 'email').omit('email').columns;
* // Result: { name: Column }
*/
export function columnSelector<T extends Table>(table: T) {
type AllColumns = T["_"]["columns"];
type ColumnSelector<C extends AllColumns> = {
select: <K extends keyof C>(...columns: K[]) => ColumnSelector<Pick<C, K>>;
omit: <K extends keyof C>(...columns: K[]) => ColumnSelector<Omit<C, K>>;
columns: C;
};
const createColumnSelector = <C extends AllColumns>(
currentColumns: C,
): ColumnSelector<C> => ({
select: <K extends keyof C>(...columns: K[]) =>
createColumnSelector(
Object.fromEntries(
Object.entries(currentColumns).filter(([key]) =>
columns.includes(key as K),
),
) as Pick<C, K>,
),
omit: <K extends keyof C>(...columns: K[]) =>
createColumnSelector(
Object.fromEntries(
Object.entries(currentColumns).filter(
([key]) => !columns.includes(key as K),
),
) as Omit<C, K>,
),
columns: currentColumns,
});
return createColumnSelector(getTableColumns(table));
}
/**
* You can use the columnSelector to create your own custom column selectors
* and use them in your queries. This allows you to define reusable selectors
* tailored to your specific needs.
*
* For example, you might want to create a selector that always omits the
* 'timeDeleted' column:
*/
function myCustomSelector<T extends Table>(table: T) {
return columnSelector(table).omit("timeDeleted").columns;
}
const columns = myCustomSelector(myTable);
// @ts-expect-error Profit!
columns.timeDeleted;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment