import {z} from 'zod' export type DeliveryStatusUpdateValue = 'not_assigned_driver' | 'assigned_driver' | 'pickup_enroute' | 'pickup_arrived' | 'items_pick_complete' | 'pickup_complete' | 'dropoff_enroute' | 'dropoff_arrived' | 'dropoff_complete' | 'failed' | 'canceled_by_provider' | 'return_in_progress' | 'return_arrived' | 'returned_to_store'; export type Coordinates = {latitude: number, longitude: number}; export type ImageProof = {podType: 'photo_proof_of_delivery' | 'signature_proof_of_delivery' | 'photo_proof_of_pickup' | 'signature_proof_of_pickup' | 'photo_pre_delivery_verification', imageUrl: string}; export type BarcodeProof = {podType: 'barcode_scan_on_pickup' | 'barcode_scan_on_dropoff' | 'barcode_scan_on_return', value: string, status: 'success' | 'invalid' | 'failure' | 'skipped' | 'manually_entered' | 'damaged'}; export type PickedItemSubstitutionType = 'no_substitution' | 'pre_selected' | 'override' | 'contact_customer'; export type PickedItem = {sku: string, requestedSku?: (string | null) | undefined, id?: (string | null) | undefined, requestedId?: (string | null) | undefined, name?: (string | null) | undefined, status: 'picked' | 'partially_picked' | 'not_picked' | 'substituted', quantity: number, requestedQuantity?: (number | null) | undefined, weight?: (number | null) | undefined, weightUnit?: (string | null) | undefined, priceCents?: (number | null) | undefined, scannedBarcode?: (string | null) | undefined, substitutionType?: (PickedItemSubstitutionType | null) | undefined, substitutionSource?: (string | null) | undefined}; export type CourierVehicle = {make?: (string | null) | undefined, model?: (string | null) | undefined, color?: (string | null) | undefined, licensePlate?: (string | null) | undefined}; export type Courier = {name?: (string | null) | undefined, phoneNumber?: (string | null) | undefined, pickupPhoneNumber?: (string | null) | undefined, dropoffPhoneNumber?: (string | null) | undefined, profileImageUrl?: (string | null) | undefined, vehicle?: (CourierVehicle | null) | undefined, externalId?: (string | null) | undefined}; export type DeliveryFailureCode = 'customer_unavailable' | 'address_not_found' | 'out_of_service_area' | 'damage_in_transit' | 'item_unavailable' | 'age_verification_failed' | 'no_capacity' | 'other'; export type DeliveryFailure = {code: DeliveryFailureCode, reason?: (string | null) | undefined}; export type DeliveryUpdate = {status?: (DeliveryStatusUpdateValue | null) | undefined, coordinates?: (Coordinates | null) | undefined, proofOfDelivery?: (Array | null) | undefined, pickedItems?: (Array | null) | undefined, courier?: (Courier | null) | undefined, failure?: (DeliveryFailure | null) | undefined, pickupNote?: (string | null) | undefined, dropoffNote?: (string | null) | undefined, parkingLocation?: (string | null) | undefined, returnParkingLocation?: (string | null) | undefined, pickupEta?: (string | null) | undefined, dropoffEta?: (string | null) | undefined, externalDeliveryId?: (string | null) | undefined}; export type PatchApiV1FleetDeliveriesDeliveryIdArgs = {delivery_id: string, body: DeliveryUpdate}; export type PatchApiV1FleetDeliveriesDeliveryIdOptions = {baseUrl?: string | undefined, fetch?: typeof fetch | undefined}; export const documentSerializer = z.object({createdAt: z.string(), id: z.string(), type: z.string(), url: z.string().nullable().optional(), data: z.string().nullable().optional(), contentType: z.string(), documentMetadata: z.record(z.string(), z.unknown()).nullable().optional()}); export const barcodeInfoSerializer = z.object({weight: z.number().nullable().optional(), priceCents: z.number().int().nullable().optional(), weightUnit: z.string().nullable().optional(), productCode: z.string().nullable().optional(), isVariableWeight: z.boolean().nullable().optional(), barcode: z.string().nullable().optional(), variableValue: z.number().nullable().optional(), format: z.string().nullable().optional(), indicatorDigit: z.string().nullable().optional(), checkDigit: z.string().nullable().optional(), manufacturerCode: z.string().nullable().optional(), itemReference: z.string().nullable().optional(), pluCheckDigit: z.string().nullable().optional(), barcodeSansCheckDigit: z.string().nullable().optional(), expirationDate: z.string().nullable().optional()}); export const itemScanSerializer = z.object({substitutionType: z.string().nullable().optional(), barcodes: z.array(barcodeInfoSerializer).nullable().optional()}); export const pickedItemsSerializer = z.object({sku: z.string().nullable().optional(), requestedSku: z.string().nullable().optional(), id: z.string().nullable().optional(), requestedId: z.string().nullable().optional(), quantity: z.number().int().nullable().optional(), requestedQuantity: z.number().int().nullable().optional(), scannedBarcode: z.string().nullable().optional(), weight: z.number().nullable().optional(), priceCents: z.number().int().nullable().optional(), status: z.string().nullable().optional(), name: z.string().nullable().optional(), scans: z.array(itemScanSerializer).nullable().optional()}); export const deliverySerializer = z.object({id: z.string(), type: z.string().nullable().optional(), status: z.string(), statusHistory: z.array(z.record(z.string(), z.unknown())).nullable().optional(), isActive: z.boolean(), pickupEta: z.string().nullable().optional(), dropoffEta: z.string().nullable().optional(), dropoffDeadline: z.string().nullable().optional(), priceCents: z.number().int(), currency: z.string(), documents: z.array(documentSerializer).nullable().optional(), nashFeeCents: z.number().int().nullable().optional(), courierName: z.string().nullable().optional(), courierPhoneNumber: z.string().nullable().optional(), courierPickupPhoneNumber: z.string().nullable().optional(), courierDropoffPhoneNumber: z.string().nullable().optional(), courierLocation: z.record(z.string(), z.unknown()).nullable().optional(), courierVehicle: z.record(z.string(), z.unknown()).nullable().optional(), courierProfileImage: z.string().nullable().optional(), proofOfDelivery: z.array(z.record(z.string(), z.unknown())).nullable().optional(), providerDeliveryId: z.string().nullable().optional(), providerBatchId: z.string().nullable().optional(), price: z.number().nullable().optional(), taxAmountCents: z.number().int().nullable().optional(), tollFeeCents: z.number().int().nullable().optional(), waitFeeCents: z.number().int().nullable().optional(), waitTimeMinutes: z.number().int().nullable().optional(), cancellationFeeCents: z.number().int().nullable().optional(), returnFeeCents: z.number().int().nullable().optional(), bonusPayCents: z.number().int().nullable().optional(), otherProviderFees: z.record(z.string(), z.unknown()).nullable().optional(), insuranceFeeCents: z.number().int().nullable().optional(), totalPriceBreakdown: z.record(z.string(), z.unknown()).nullable().optional(), totalPriceCents: z.number().int().nullable().optional(), pickedItems: z.array(pickedItemsSerializer).nullable().optional()}); 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 }; /** * Update Delivery * * PATCH /v1/fleet/deliveries/{delivery_id} */ export const patchApiV1FleetDeliveriesDeliveryId = async (args: PatchApiV1FleetDeliveriesDeliveryIdArgs, options?: PatchApiV1FleetDeliveriesDeliveryIdOptions) => { const {baseUrl = "https://api.sandbox.usenash.com", fetch: fetchFn = fetch} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('content-type', "application/json") headers.set('accept', "application/json") const url = `${baseUrl.replace(/\/+$/, '')}/v1/fleet/deliveries/${encodeURIComponent(String(args.delivery_id))}${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "PATCH", headers, body: JSON.stringify(args.body)}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(deliverySerializer, await res.json()) };