import {z} from 'zod' export type GetApiCrbsCrbIdProductsArgs = {crb_id: string, limit?: number | undefined, offset?: number | undefined, last_updated_from?: string | undefined, last_updated_to?: string | undefined}; export type GetApiCrbsCrbIdProductsOptions = {baseUrl?: string | undefined, accessAuth?: string | undefined, fetch?: typeof fetch | undefined}; export const positiveInteger = z.number().int().gte(0); export const uUID = z.string(); export const friendlyPosName = z.enum(["Alleaves", "Apex Trading Wholesale", "Dutchie", "Dutchie Wholesale", "Cova", "Meadow", "MJ Freeway", "MJ Freeway Wholesale", "Greenbits", "GrowFlow", "GrowFlow Wholesale", "Portal42", "Metrc S2S", "Metrc S2S Wholesale", "Flourish", "Flourish Wholesale", "Flowhub", "BioTrack", "BioTrack Wholesale", "Treez", "Blaze", "Quickbooks", "Sage Intacct", "Canix", "Brytemap", "POSaBIT", "Proteus420", "IndicaOnline", "Sweed", "Weave", "Jane", "Manual Upload Wholesale", "Cova Test Account", "Leaf Logix Test Account", "BioTrack Test Account", "Mj Freeway Test Account", "Treez IO Test Account", "Green Bits Test Account", "Manual Upload Retail", "SFTP Sales Retail", "SFTP Sales Wholesale", "Not Configured", "Unsupported", "CRBMonitor", "Plaid"]); export const productCategoryType = z.enum(["flower", "oil/concentrate", "edible", "other", "seedling", "seed", "liquid", "solid", "extract", "plant", "accessory", "marijuana_product", "topical", "edible_liquid"]).nullable(); export const nullablePositiveDouble = z.number().gte(0).nullable(); export const nullablePositiveInteger = z.number().int().gte(0).nullable(); export const nullableUtcDateTime = z.string().nullable(); export const nullableLocalDateTime = z.string().nullable(); export const utcDateTime = z.string(); export const productPriceTier = z.object({tier_name: z.string().nullable(), tier_price: positiveInteger, pos_tier_type: z.string(), pos_tier_type_condition_value: z.string(), tier_valid_until_date: nullableUtcDateTime, tier_valid_until_date_local: nullableLocalDateTime}); export const productImage = z.object({url: z.string(), description: z.string().nullable()}); export const product = z.object({crb_id: uUID, id: uUID, pos_product_id: z.string(), pos_type: friendlyPosName, name: z.string(), gc_product_category_name: productCategoryType, pos_product_category_name: z.string().nullable(), pos_product_subcategory_name: z.string().nullable(), pos_strain_name: z.string().nullable(), pos_brand_name: z.string().nullable(), medicated: z.boolean().nullable(), sku: z.string().nullable(), description: z.string().nullable(), gc_net_weight_grams: nullablePositiveDouble, pos_unit_of_measure: z.string().nullable(), price: nullablePositiveInteger, unit_cost: nullablePositiveDouble, pos_updated_date: nullableUtcDateTime, pos_updated_date_local: nullableLocalDateTime, gc_created_date: utcDateTime, gc_updated_date: utcDateTime, price_tiers: z.array(productPriceTier).nullable(), images: z.array(productImage).nullable()}); export const pagedProducts = z.object({metadata: z.object({total: positiveInteger, count: z.string()}), data: z.array(product)}); export const validateResponse = async ( schema: { readonly '~standard': { readonly validate: (value: unknown) => ({ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }) | Promise<{ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }> } }, value: unknown ): Promise => { const result = await schema['~standard'].validate(value) if (result.issues !== undefined) { const detail = result.issues .map(({ message, path }) => path?.length ? `${path.map((segment) => String(typeof segment === 'object' ? segment.key : segment)).join('.')}: ${message}` : message ) .join('; ') throw new Error(`Response does not match the schema: ${detail}`, { cause: { issues: result.issues } }) } return result.value }; /** * Get CRB products * * GET /crbs/{crb_id}/products */ export const getApiCrbsCrbIdProducts = async (args: GetApiCrbsCrbIdProductsArgs, options?: GetApiCrbsCrbIdProductsOptions) => { const {baseUrl = "https://sandbox-api.greencheckverified.com", fetch: fetchFn = fetch, accessAuth} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('accept', "application/json") if (args.limit != null) query.append("limit", String(args.limit)) if (args.offset != null) query.append("offset", String(args.offset)) if (args.last_updated_from != null) query.append("last_updated_from", String(args.last_updated_from)) if (args.last_updated_to != null) query.append("last_updated_to", String(args.last_updated_to)) if (accessAuth !== undefined) headers.set("Authorization", accessAuth) const url = `${baseUrl.replace(/\/+$/, '')}/crbs/${encodeURIComponent(String(args.crb_id))}/products${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "GET", headers}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(pagedProducts, await res.json()) };