mirror of https://github.com/buster-so/buster.git
array parter
This commit is contained in:
parent
5dc31814d8
commit
0d01dfcb4c
|
@ -14,6 +14,8 @@ const app = new Hono().get(
|
||||||
const { id: userId } = c.get('busterUser');
|
const { id: userId } = c.get('busterUser');
|
||||||
const options = c.req.valid('query');
|
const options = c.req.valid('query');
|
||||||
|
|
||||||
|
console.log(options);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result: GetUserToOrganizationResponse = await getUserToOrganization({
|
const result: GetUserToOrganizationResponse = await getUserToOrganization({
|
||||||
userId,
|
userId,
|
||||||
|
|
|
@ -1,7 +1,13 @@
|
||||||
import { type InferSelectModel, and, asc, count, eq, isNull, like } from 'drizzle-orm';
|
import { type InferSelectModel, and, asc, count, eq, inArray, isNull, like } from 'drizzle-orm';
|
||||||
|
import { createSelectSchema } from 'drizzle-zod';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
import { db } from '../../connection';
|
import { db } from '../../connection';
|
||||||
import { users, usersToOrganizations } from '../../schema';
|
import {
|
||||||
|
userOrganizationRoleEnum,
|
||||||
|
userOrganizationStatusEnum,
|
||||||
|
users,
|
||||||
|
usersToOrganizations,
|
||||||
|
} from '../../schema';
|
||||||
import { getUserOrganizationId } from '../organizations/organizations';
|
import { getUserOrganizationId } from '../organizations/organizations';
|
||||||
import { type PaginatedResponse, createPaginatedResponse } from '../shared-types';
|
import { type PaginatedResponse, createPaginatedResponse } from '../shared-types';
|
||||||
import { withPagination } from '../shared-types/with-pagination';
|
import { withPagination } from '../shared-types/with-pagination';
|
||||||
|
@ -17,6 +23,8 @@ const GetUserToOrganizationInputSchema = z.object({
|
||||||
page_size: z.number().optional().default(250),
|
page_size: z.number().optional().default(250),
|
||||||
user_name: z.string().optional(),
|
user_name: z.string().optional(),
|
||||||
email: z.string().optional(),
|
email: z.string().optional(),
|
||||||
|
role: z.array(z.enum(userOrganizationRoleEnum.enumValues)).optional(),
|
||||||
|
status: z.array(z.enum(userOrganizationStatusEnum.enumValues)).optional(),
|
||||||
});
|
});
|
||||||
|
|
||||||
type GetUserToOrganizationInput = z.infer<typeof GetUserToOrganizationInputSchema>;
|
type GetUserToOrganizationInput = z.infer<typeof GetUserToOrganizationInputSchema>;
|
||||||
|
@ -33,7 +41,7 @@ export const getUserToOrganization = async (
|
||||||
params: GetUserToOrganizationInput
|
params: GetUserToOrganizationInput
|
||||||
): Promise<PaginatedResponse<OrganizationUser>> => {
|
): Promise<PaginatedResponse<OrganizationUser>> => {
|
||||||
// Validate and destructure input
|
// Validate and destructure input
|
||||||
const { userId, page, page_size, user_name, email } =
|
const { userId, page, page_size, user_name, email, role, status } =
|
||||||
GetUserToOrganizationInputSchema.parse(params);
|
GetUserToOrganizationInputSchema.parse(params);
|
||||||
|
|
||||||
// Get the user's organization ID
|
// Get the user's organization ID
|
||||||
|
@ -49,7 +57,9 @@ export const getUserToOrganization = async (
|
||||||
eq(usersToOrganizations.organizationId, organizationId),
|
eq(usersToOrganizations.organizationId, organizationId),
|
||||||
isNull(usersToOrganizations.deletedAt),
|
isNull(usersToOrganizations.deletedAt),
|
||||||
user_name ? like(users.name, `%${user_name}%`) : undefined,
|
user_name ? like(users.name, `%${user_name}%`) : undefined,
|
||||||
email ? like(users.email, `%${email}%`) : undefined
|
email ? like(users.email, `%${email}%`) : undefined,
|
||||||
|
role ? inArray(usersToOrganizations.role, role) : undefined,
|
||||||
|
status ? inArray(usersToOrganizations.status, status) : undefined
|
||||||
);
|
);
|
||||||
|
|
||||||
const getData = withPagination(
|
const getData = withPagination(
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
export * from './isEqual';
|
export * from './isEqual';
|
||||||
export * from './pagination';
|
export * from './pagination';
|
||||||
|
export * from './query-array-preprocessor';
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a preprocessor that converts query parameter strings into arrays.
|
||||||
|
* Handles various input formats:
|
||||||
|
* - Single value: "admin" → ["admin"]
|
||||||
|
* - Comma-separated: "admin,member" → ["admin", "member"]
|
||||||
|
* - Already an array: ["admin", "member"] → ["admin", "member"]
|
||||||
|
* - No value: undefined → undefined
|
||||||
|
*/
|
||||||
|
export const createQueryArrayPreprocessor = <T>(schema: z.ZodArray<z.ZodType<T>>) => {
|
||||||
|
return z.preprocess((val) => {
|
||||||
|
// Handle no value
|
||||||
|
if (!val) return undefined;
|
||||||
|
|
||||||
|
// Already an array, pass through
|
||||||
|
if (Array.isArray(val)) return val;
|
||||||
|
|
||||||
|
// Handle string input (single or comma-separated)
|
||||||
|
if (typeof val === 'string') {
|
||||||
|
return val
|
||||||
|
.split(',')
|
||||||
|
.map((item) => item.trim())
|
||||||
|
.filter(Boolean);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Single value case (wrap in array)
|
||||||
|
return [val];
|
||||||
|
}, schema);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type-safe helper for creating optional query array preprocessors
|
||||||
|
*/
|
||||||
|
export const createOptionalQueryArrayPreprocessor = <T>(itemSchema: z.ZodType<T>) => {
|
||||||
|
return z.preprocess((val) => {
|
||||||
|
// Handle no value
|
||||||
|
if (!val) return undefined;
|
||||||
|
|
||||||
|
// Already an array, pass through
|
||||||
|
if (Array.isArray(val)) return val;
|
||||||
|
|
||||||
|
// Handle string input (single or comma-separated)
|
||||||
|
if (typeof val === 'string') {
|
||||||
|
return val
|
||||||
|
.split(',')
|
||||||
|
.map((item) => item.trim())
|
||||||
|
.filter(Boolean);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Single value case (wrap in array)
|
||||||
|
return [val];
|
||||||
|
}, z.array(itemSchema).optional());
|
||||||
|
};
|
|
@ -1,6 +1,8 @@
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
import { OrganizationStatusSchema } from '../organization';
|
||||||
import { OrganizationRoleSchema } from '../organization/roles.types';
|
import { OrganizationRoleSchema } from '../organization/roles.types';
|
||||||
import { ShareAssetTypeSchema } from '../share';
|
import { ShareAssetTypeSchema } from '../share';
|
||||||
|
import { createOptionalQueryArrayPreprocessor } from '../type-utilities';
|
||||||
|
|
||||||
export const UserRequestSchema = z.object({
|
export const UserRequestSchema = z.object({
|
||||||
user_id: z.string(),
|
user_id: z.string(),
|
||||||
|
@ -50,9 +52,13 @@ export type GetUserListRequest = z.infer<typeof GetUserListRequestSchema>;
|
||||||
|
|
||||||
export const GetUserToOrganizationRequestSchema = z.object({
|
export const GetUserToOrganizationRequestSchema = z.object({
|
||||||
page: z.coerce.number().min(1).optional().default(1),
|
page: z.coerce.number().min(1).optional().default(1),
|
||||||
page_size: z.coerce.number().min(1).max(5000).optional().default(250),
|
page_size: z.coerce.number().min(1).max(5000).optional().default(25),
|
||||||
user_name: z.string().optional(),
|
user_name: z.string().optional(),
|
||||||
email: z.string().optional(),
|
email: z.string().optional(),
|
||||||
|
//We need this because the frontend sends the roles as a comma-separated string in the query params
|
||||||
|
role: createOptionalQueryArrayPreprocessor(OrganizationRoleSchema),
|
||||||
|
//We need this because the frontend sends the status as a comma-separated string in the query params
|
||||||
|
status: createOptionalQueryArrayPreprocessor(OrganizationStatusSchema),
|
||||||
});
|
});
|
||||||
|
|
||||||
export type GetUserToOrganizationRequest = z.infer<typeof GetUserToOrganizationRequestSchema>;
|
export type GetUserToOrganizationRequest = z.infer<typeof GetUserToOrganizationRequestSchema>;
|
||||||
|
|
Loading…
Reference in New Issue