Implement paginated endpoint to list users and their organizations created by master org through the platform exchange flow. ## Changes - Create shared/api/platform/platformModels.ts with Zod schemas for query params and response types - Implement handleListPlatformUsers handler with pagination support (limit/offset) - Add expand=organizations query param to fetch up to 100 orgs per user - Clean org slugs by removing master org prefix in responses - Create honoPlatformRouter and register it in Hono app at /v1/platform/users - Export platform types from shared package index - Apply biome linting fixes to platformRouter.ts (let -> const conversions) ## Features ✅ Paginated results (limit 1-100, default 10) ✅ Offset-based pagination matching handleBatchCustomers pattern ✅ Optional organizations expansion ✅ Filters by organizations.created_by = ctx.org_id ✅ Removes master org slug prefix from org responses 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
77 lines
2.0 KiB
TypeScript
77 lines
2.0 KiB
TypeScript
import { z } from "zod/v4";
|
|
|
|
/**
|
|
* Query params for GET /platform/users endpoint
|
|
*/
|
|
export const ListPlatformUsersQuerySchema = z.object({
|
|
limit: z
|
|
.number({
|
|
invalid_type_error: "limit must be a number",
|
|
})
|
|
.int({ message: "limit must be an integer" })
|
|
.min(1, { message: "limit must be at least 1" })
|
|
.max(100, { message: "limit must be at most 100" })
|
|
.default(10),
|
|
|
|
offset: z
|
|
.number({
|
|
invalid_type_error: "offset must be a number",
|
|
})
|
|
.int({ message: "offset must be an integer" })
|
|
.min(0, { message: "offset must be at least 0" })
|
|
.default(0),
|
|
|
|
expand: z
|
|
.enum(["organizations"])
|
|
.optional()
|
|
.describe(
|
|
"Comma-separated list of fields to expand. Currently supports: organizations",
|
|
),
|
|
});
|
|
|
|
export type ListPlatformUsersQuery = z.infer<
|
|
typeof ListPlatformUsersQuerySchema
|
|
>;
|
|
|
|
/**
|
|
* Platform organization schema
|
|
*/
|
|
export const ApiPlatformOrgSchema = z.object({
|
|
slug: z.string().describe("Organization slug without the master org prefix"),
|
|
name: z.string().describe("Organization name"),
|
|
created_at: z.string().describe("ISO 8601 timestamp of when org was created"),
|
|
});
|
|
|
|
export type ApiPlatformOrg = z.infer<typeof ApiPlatformOrgSchema>;
|
|
|
|
/**
|
|
* Platform user schema
|
|
*/
|
|
export const ApiPlatformUserSchema = z.object({
|
|
name: z.string().describe("User name"),
|
|
email: z.string().describe("User email"),
|
|
created_at: z
|
|
.string()
|
|
.describe("ISO 8601 timestamp of when user was created"),
|
|
organizations: z
|
|
.array(ApiPlatformOrgSchema)
|
|
.optional()
|
|
.describe("List of organizations created by the master org for this user"),
|
|
});
|
|
|
|
export type ApiPlatformUser = z.infer<typeof ApiPlatformUserSchema>;
|
|
|
|
/**
|
|
* Response schema for GET /platform/users
|
|
*/
|
|
export const ListPlatformUsersResponseSchema = z.object({
|
|
list: z.array(ApiPlatformUserSchema),
|
|
total: z.number().describe("Total number of users returned"),
|
|
limit: z.number().describe("Limit used in the query"),
|
|
offset: z.number().describe("Offset used in the query"),
|
|
});
|
|
|
|
export type ListPlatformUsersResponse = z.infer<
|
|
typeof ListPlatformUsersResponseSchema
|
|
>;
|