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 BulkDeliveryUpdateItem = {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, deliveryId?: (string | null) | undefined, packageExternalIdentifier?: (string | null) | undefined}; export type BulkDeliveryUpdateRequest = {deliveries: Array}; export type PatchApiV1FleetDeliveriesArgs = {body: BulkDeliveryUpdateRequest}; export type PatchApiV1FleetDeliveriesOptions = {baseUrl?: string | undefined, fetch?: typeof fetch | undefined}; export const bulkDeliveryUpdateResultItem = z.object({deliveryId: z.string(), success: z.boolean(), errorCode: z.string().nullable().optional(), errorMessage: z.string().nullable().optional(), delivery: z.record(z.string(), z.unknown()).nullable().optional()}); export const bulkDeliveryUpdateResponse = z.object({results: z.array(bulkDeliveryUpdateResultItem)}); 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 }; /** * Bulk Update Deliveries * * PATCH /v1/fleet/deliveries */ export const patchApiV1FleetDeliveries = async (args: PatchApiV1FleetDeliveriesArgs, options?: PatchApiV1FleetDeliveriesOptions) => { 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${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(bulkDeliveryUpdateResponse, await res.json()) };