import { ISiteAdapter } from '../interface/site-adapter.interface'; import { IPlatformService } from '../interface/platform.interface'; import { UnifiedMediaDTO, UnifiedOrderDTO, UnifiedPaginationDTO, UnifiedProductDTO, UnifiedSearchParamsDTO, UnifiedSubscriptionDTO, UnifiedCustomerDTO, UnifiedReviewPaginationDTO, UnifiedReviewDTO, UnifiedWebhookDTO, UnifiedWebhookPaginationDTO, CreateWebhookDTO, UpdateWebhookDTO, } from '../dto/site-api.dto'; import { WooProduct, WooOrder, WooSubscription, WpMedia, WooCustomer, WooWebhook, WooOrderSearchParams, WooProductSearchParams, } from '../dto/woocommerce.dto'; import { Site } from '../entity/site.entity'; export class WooCommerceAdapter implements ISiteAdapter { // 构造函数接收站点配置与服务实例 constructor(private site: Site, private wpService: IPlatformService) { this.mapProduct = this.mapProduct.bind(this); this.mapReview = this.mapReview.bind(this); this.mapCustomer = this.mapCustomer.bind(this); this.mapMedia = this.mapMedia.bind(this); this.mapOrder = this.mapOrder.bind(this); this.mapWebhook = this.mapWebhook.bind(this); } // 映射 WooCommerce webhook 到统一格式 private mapWebhook(webhook: WooWebhook): UnifiedWebhookDTO { return { id: webhook.id.toString(), name: webhook.name, status: webhook.status, topic: webhook.topic, delivery_url: webhook.delivery_url, secret: webhook.secret, api_version: webhook.api_version, date_created: webhook.date_created, date_modified: webhook.date_modified, // metadata: webhook.meta_data || [], }; } // 获取站点的 webhooks 列表 async getWebhooks(params: UnifiedSearchParamsDTO): Promise { try { const result = await this.wpService.getWebhooks(this.site, params); return { items: (result.items as WooWebhook[]).map(this.mapWebhook), total: result.total, page: Number(params.page || 1), per_page: Number(params.per_page || 20), totalPages: result.totalPages, }; } catch (error) { throw new Error(`Failed to get webhooks: ${error instanceof Error ? error.message : String(error)}`); } } // 获取单个 webhook 详情 async getWebhook(id: string | number): Promise { try { const result = await this.wpService.getWebhook(this.site, id); return this.mapWebhook(result as WooWebhook); } catch (error) { throw new Error(`Failed to get webhook: ${error instanceof Error ? error.message : String(error)}`); } } // 创建新的 webhook async createWebhook(data: CreateWebhookDTO): Promise { try { const params = { name: data.name, status: 'active', // 默认状态为活跃 topic: data.topic, delivery_url: data.delivery_url, secret: data.secret, api_version: data.api_version || 'wp/v2', }; const result = await this.wpService.createWebhook(this.site, params); return this.mapWebhook(result as WooWebhook); } catch (error) { throw new Error(`Failed to create webhook: ${error instanceof Error ? error.message : String(error)}`); } } // 更新现有的 webhook async updateWebhook(id: string | number, data: UpdateWebhookDTO): Promise { try { const params = { ...(data.name ? { name: data.name } : {}), ...(data.status ? { status: data.status } : {}), ...(data.topic ? { topic: data.topic } : {}), ...(data.delivery_url ? { delivery_url: data.delivery_url } : {}), ...(data.secret ? { secret: data.secret } : {}), ...(data.api_version ? { api_version: data.api_version } : {}), }; const result = await this.wpService.updateWebhook(this.site, id, params); return this.mapWebhook(result as WooWebhook); } catch (error) { throw new Error(`Failed to update webhook: ${error instanceof Error ? error.message : String(error)}`); } } // 删除指定的 webhook async deleteWebhook(id: string | number): Promise { try { await this.wpService.deleteWebhook(this.site, id); return true; } catch (error) { throw new Error(`Failed to delete webhook: ${error instanceof Error ? error.message : String(error)}`); } } async getLinks(): Promise> { const baseUrl = this.site.apiUrl; const links = [ { title: '访问网站', url: baseUrl }, { title: '管理后台', url: `${baseUrl}/wp-admin/` }, { title: '订单管理', url: `${baseUrl}/wp-admin/edit.php?post_type=shop_order` }, { title: '产品管理', url: `${baseUrl}/wp-admin/edit.php?post_type=product` }, { title: '客户管理', url: `${baseUrl}/wp-admin/users.php` }, { title: '插件管理', url: `${baseUrl}/wp-admin/plugins.php` }, { title: '主题管理', url: `${baseUrl}/wp-admin/themes.php` }, { title: 'WooCommerce设置', url: `${baseUrl}/wp-admin/admin.php?page=wc-settings` }, { title: 'WooCommerce报告', url: `${baseUrl}/wp-admin/admin.php?page=wc-reports` }, ]; return links; } createMedia(file: any): Promise { throw new Error('Method not implemented.'); } batchProcessOrders?(data: { create?: any[]; update?: any[]; delete?: Array; }): Promise { throw new Error('Method not implemented.'); } batchProcessCustomers?(data: { create?: any[]; update?: any[]; delete?: Array; }): Promise { throw new Error('Method not implemented.'); } private mapProductSearchParams(params: UnifiedSearchParamsDTO): Partial { const page = Number(params.page ?? 1); const per_page = Number( params.per_page ?? 20); const where = params.where && typeof params.where === 'object' ? params.where : {}; const mapped: any = { ...(params.search ? { search: params.search } : {}), ...(where.status ? { status: where.status } : {}), page, per_page, }; const toArray = (value: any): any[] => { if (Array.isArray(value)) return value; if (value === undefined || value === null) return []; return String(value).split(',').map(v => v.trim()).filter(Boolean); }; if (where.search_fields ?? where.searchFields) mapped.search_fields = toArray(where.search_fields ?? where.searchFields); if (where.after ?? where.date_created_after ?? where.created_after) mapped.after = String(where.after ?? where.date_created_after ?? where.created_after); if (where.before ?? where.date_created_before ?? where.created_before) mapped.before = String(where.before ?? where.date_created_before ?? where.created_before); if (where.modified_after ?? where.date_modified_after) mapped.modified_after = String(where.modified_after ?? where.date_modified_after); if (where.modified_before ?? where.date_modified_before) mapped.modified_before = String(where.modified_before ?? where.date_modified_before); if (where.dates_are_gmt ?? where.datesAreGmt) mapped.dates_are_gmt = Boolean(where.dates_are_gmt ?? where.datesAreGmt); if (where.exclude ?? where.exclude_ids ?? where.excludedIds) mapped.exclude = toArray(where.exclude ?? where.exclude_ids ?? where.excludedIds); if (where.include ?? where.ids) mapped.include = toArray(where.include ?? where.ids); if (where.offset !== undefined) mapped.offset = Number(where.offset); if (where.parent ?? where.parentId) mapped.parent = toArray(where.parent ?? where.parentId); if (where.parent_exclude ?? where.parentExclude) mapped.parent_exclude = toArray(where.parent_exclude ?? where.parentExclude); if (where.slug) mapped.slug = String(where.slug); if (!mapped.status && (where.status || where.include_status || where.exclude_status || where.includeStatus || where.excludeStatus)) { if (where.include_status ?? where.includeStatus) mapped.include_status = String(where.include_status ?? where.includeStatus); if (where.exclude_status ?? where.excludeStatus) mapped.exclude_status = String(where.exclude_status ?? where.excludeStatus); if (where.status) mapped.status = String(where.status); } if (where.type) mapped.type = String(where.type); if (where.include_types ?? where.includeTypes) mapped.include_types = String(where.include_types ?? where.includeTypes); if (where.exclude_types ?? where.excludeTypes) mapped.exclude_types = String(where.exclude_types ?? where.excludeTypes); if (where.sku) mapped.sku = String(where.sku); if (where.featured ?? where.isFeatured) mapped.featured = Boolean(where.featured ?? where.isFeatured); if (where.category ?? where.categoryId) mapped.category = String(where.category ?? where.categoryId); if (where.tag ?? where.tagId) mapped.tag = String(where.tag ?? where.tagId); if (where.shipping_class ?? where.shippingClass) mapped.shipping_class = String(where.shipping_class ?? where.shippingClass); if (where.attribute ?? where.attributeName) mapped.attribute = String(where.attribute ?? where.attributeName); if (where.attribute_term ?? where.attributeTermId ?? where.attributeTerm) mapped.attribute_term = String(where.attribute_term ?? where.attributeTermId ?? where.attributeTerm); if (where.tax_class ?? where.taxClass) mapped.tax_class = String(where.tax_class ?? where.taxClass); if (where.on_sale ?? where.onSale) mapped.on_sale = Boolean(where.on_sale ?? where.onSale); if (where.min_price ?? where.minPrice) mapped.min_price = String(where.min_price ?? where.minPrice); if (where.max_price ?? where.maxPrice) mapped.max_price = String(where.max_price ?? where.maxPrice); if (where.stock_status ?? where.stockStatus) mapped.stock_status = String(where.stock_status ?? where.stockStatus); if (where.virtual !== undefined) mapped.virtual = Boolean(where.virtual); if (where.downloadable !== undefined) mapped.downloadable = Boolean(where.downloadable); return mapped; } private mapOrderSearchParams(params: UnifiedSearchParamsDTO): Partial { // 计算分页参数 const page = Number(params.page ?? 1); const per_page = Number( params.per_page ?? 20); // 解析排序参数 支持从 order 对象推导 const where = params.where && typeof params.where === 'object' ? params.where : {}; // if (params.orderBy && typeof params.orderBy === 'object') { // } const mapped: any = { ...(params.search ? { search: params.search } : {}), // ...(orderBy ? { orderBy } : {}), page, per_page, }; const toArray = (value: any): any[] => { if (Array.isArray(value)) return value; if (value === undefined || value === null) return []; return String(value).split(',').map(v => v.trim()).filter(Boolean); }; const toNumber = (value: any): number | undefined => { if (value === undefined || value === null || value === '') return undefined; const n = Number(value); return Number.isFinite(n) ? n : undefined; }; // 时间过滤参数 if (where.after ?? where.date_created_after ?? where.created_after) mapped.after = String(where.after ?? where.date_created_after ?? where.created_after); if (where.before ?? where.date_created_before ?? where.created_before) mapped.before = String(where.before ?? where.date_created_before ?? where.created_before); if (where.modified_after ?? where.date_modified_after) mapped.modified_after = String(where.modified_after ?? where.date_modified_after); if (where.modified_before ?? where.date_modified_before) mapped.modified_before = String(where.modified_before ?? where.date_modified_before); if (where.dates_are_gmt ?? where.datesAreGmt) mapped.dates_are_gmt = Boolean(where.dates_are_gmt ?? where.datesAreGmt); // 集合过滤参数 if (where.exclude) mapped.exclude = toArray(where.exclude); if (where.include) mapped.include = toArray(where.include); if (where.ids) mapped.include = toArray(where.ids); if (toNumber(where.offset) !== undefined) mapped.offset = Number(where.offset); if (where.parent ?? where.parentId) mapped.parent = toArray(where.parent ?? where.parentId); if (where.parent_exclude ?? where.parentExclude) mapped.parent_exclude = toArray(where.parent_exclude ?? where.parentExclude); // 状态过滤 参数支持数组或逗号分隔字符串 const statusSource = where.status; if (statusSource !== undefined) { mapped.status = Array.isArray(statusSource) ? statusSource.map(s => String(s)) : String(statusSource).split(',').map(s => s.trim()).filter(Boolean); } // 客户与产品过滤 const customerVal = where.customer ?? where.customer_id; const productVal = where.product ?? where.product_id; const dpVal = where.dp; if (toNumber(customerVal) !== undefined) mapped.customer = Number(customerVal); if (toNumber(productVal) !== undefined) mapped.product = Number(productVal); if (toNumber(dpVal) !== undefined) mapped.dp = Number(dpVal); // 创建来源过滤 支持逗号分隔 const createdViaVal = where.created_via; if (createdViaVal !== undefined) mapped.created_via = Array.isArray(createdViaVal) ? createdViaVal.join(',') : String(createdViaVal); return mapped; } private mapCustomerSearchParams(params: UnifiedSearchParamsDTO): Record { const page = Number(params.page ?? 1); const per_page = Number(params.per_page ?? 20); const where = params.where && typeof params.where === 'object' ? params.where : {}; const mapped: any = { ...(params.search ? { search: params.search } : {}), page, per_page, }; const toArray = (value: any): any[] => { if (Array.isArray(value)) return value; if (value === undefined || value === null) return []; return String(value).split(',').map(v => v.trim()).filter(Boolean); }; const toNumber = (value: any): number | undefined => { if (value === undefined || value === null || value === '') return undefined; const n = Number(value); return Number.isFinite(n) ? n : undefined; }; if (where.exclude) mapped.exclude = toArray(where.exclude); if (where.include) mapped.include = toArray(where.include); if (where.ids) mapped.include = toArray(where.ids); if (toNumber(where.offset) !== undefined) mapped.offset = Number(where.offset); if (where.email) mapped.email = String(where.email); const roleSource = where.role; if (roleSource !== undefined) mapped.role = String(roleSource); return mapped; } private mapProduct(item: WooProduct): UnifiedProductDTO { // 将 WooCommerce 产品数据映射为统一产品DTO // 保留常用字段与时间信息以便前端统一展示 // https://woocommerce.github.io/woocommerce-rest-api-docs/?javascript#product-properties return { id: item.id, date_created: item.date_created, date_modified: item.date_modified, type: item.type, // simple grouped external variable status: item.status, // draft pending private publish sku: item.sku, name: item.name, //价格 regular_price: item.regular_price, sale_price: item.sale_price, price: item.price, stock_status: item.stock_status, stock_quantity: item.stock_quantity, images: (item.images || []).map((img: any) => ({ id: img.id, src: img.src, name: img.name, alt: img.alt, })), categories: (item.categories || []).map((c: any) => ({ id: c.id, name: c.name, })), tags: (item.tags || []).map((t: any) => ({ id: t.id, name: t.name, })), attributes: (item.attributes || []).map(attr => ({ id: attr.id, name: attr.name || '', position: attr.position, visible: attr.visible, variation: attr.variation, options: attr.options || [] })), variations: item.variations as any, permalink: item.permalink, raw: item, }; } private buildFullAddress(addr: any): string { if (!addr) return ''; const name = addr.fullname || `${addr.first_name || ''} ${addr.last_name || ''}`.trim(); return [ name, addr.company, addr.address_1, addr.address_2, addr.city, addr.state, addr.postcode, addr.country, addr.phone ].filter(Boolean).join(', '); } private mapOrder(item: WooOrder): UnifiedOrderDTO { // 将 WooCommerce 订单数据映射为统一订单DTO // 包含账单地址与收货地址以及创建与更新时间 return { id: item.id, number: item.number, status: item.status, currency: item.currency, total: item.total, customer_id: item.customer_id, customer_name: `${item.billing?.first_name || ''} ${ item.billing?.last_name || '' }`.trim(), refunds: item.refunds?.map?.(refund => ({ id: refund.id, reason: refund.reason, total: refund.total, })), email: item.billing?.email || '', line_items: (item.line_items as any[]).map(li => ({ ...li, productId: li.product_id, })), billing: item.billing, shipping: item.shipping, billing_full_address: this.buildFullAddress(item.billing), shipping_full_address: this.buildFullAddress(item.shipping), payment_method: item.payment_method_title, date_created: item.date_created, date_modified: item.date_modified, raw: item, }; } private mapSubscription(item: WooSubscription): UnifiedSubscriptionDTO { // 将 WooCommerce 订阅数据映射为统一订阅DTO // 若缺少创建时间则回退为开始时间 return { id: item.id, status: item.status, customer_id: item.customer_id, billing_period: item.billing_period, billing_interval: item.billing_interval, date_created: item.date_created ?? item.start_date, date_modified: item.date_modified, start_date: item.start_date, next_payment_date: item.next_payment_date, line_items: item.line_items, raw: item, }; } private mapMedia(item: WpMedia): UnifiedMediaDTO { // 将 WordPress 媒体数据映射为统一媒体DTO // 兼容不同字段命名的时间信息 return { id: item.id, title: typeof item.title === 'string' ? item.title : item.title?.rendered || '', media_type: item.media_type, mime_type: item.mime_type, source_url: item.source_url, date_created: item.date_created ?? item.date, date_modified: item.date_modified ?? item.modified, }; } async getProducts( params: UnifiedSearchParamsDTO ): Promise> { // 获取产品列表并使用统一分页结构返回 const requestParams = this.mapProductSearchParams(params); const { items, total, totalPages, page, per_page } = await this.wpService.fetchResourcePaged( this.site, 'products', requestParams ); return { items: items.map(this.mapProduct), total, totalPages, page, per_page, }; } async getProduct(id: string | number): Promise { // 获取单个产品详情并映射为统一产品DTO const api = (this.wpService as any).createApi(this.site, 'wc/v3'); const res = await api.get(`products/${id}`); return this.mapProduct(res.data); } async createProduct(data: Partial): Promise { // 创建产品并返回统一产品DTO const res = await this.wpService.createProduct(this.site, data); return this.mapProduct(res); } async updateProduct(id: string | number, data: Partial): Promise { // 更新产品并返回统一产品DTO const res = await this.wpService.updateProduct(this.site, String(id), data as any); return res } async updateVariation(productId: string | number, variationId: string | number, data: any): Promise { // 更新变体信息并返回结果 const res = await this.wpService.updateVariation(this.site, String(productId), String(variationId), data); return res; } async getOrderNotes(orderId: string | number): Promise { // 获取订单备注列表 const api = (this.wpService as any).createApi(this.site, 'wc/v3'); const res = await api.get(`orders/${orderId}/notes`); return res.data; } async createOrderNote(orderId: string | number, data: any): Promise { // 创建订单备注 const api = (this.wpService as any).createApi(this.site, 'wc/v3'); const res = await api.post(`orders/${orderId}/notes`, data); return res.data; } async deleteProduct(id: string | number): Promise { // 删除产品 const api = (this.wpService as any).createApi(this.site, 'wc/v3'); try { await api.delete(`products/${id}`, { force: true }); return true; } catch (e) { return false; } } async batchProcessProducts( data: { create?: any[]; update?: any[]; delete?: Array } ): Promise { // 批量处理产品增删改 return await this.wpService.batchProcessProducts(this.site, data); } async getOrders( params: UnifiedSearchParamsDTO ): Promise> { const requestParams = this.mapOrderSearchParams(params); const { items, total, totalPages, page, per_page } = await this.wpService.fetchResourcePaged(this.site, 'orders', requestParams); return { items: items.map(this.mapOrder), total, totalPages, page, per_page, }; } async getOrder(id: string | number): Promise { // 获取单个订单详情 const api = (this.wpService as any).createApi(this.site, 'wc/v3'); const res = await api.get(`orders/${id}`); return this.mapOrder(res.data); } async createOrder(data: Partial): Promise { // 创建订单并返回统一订单DTO const api = (this.wpService as any).createApi(this.site, 'wc/v3'); const res = await api.post('orders', data); return this.mapOrder(res.data); } async updateOrder(id: string | number, data: Partial): Promise { // 更新订单并返回布尔结果 return await this.wpService.updateOrder(this.site, String(id), data as any); } async deleteOrder(id: string | number): Promise { // 删除订单 const api = (this.wpService as any).createApi(this.site, 'wc/v3'); await api.delete(`orders/${id}`, { force: true }); return true; } async shipOrder(orderId: string | number, data: { tracking_number?: string; shipping_provider?: string; shipping_method?: string; items?: Array<{ order_item_id: number; quantity: number; }>; }): Promise { throw new Error('暂无实现') // 订单发货 // const api = (this.wpService as any).createApi(this.site, 'wc/v3'); // try { // // 更新订单状态为已完成 // await api.put(`orders/${orderId}`, { status: 'completed' }); // // 如果提供了物流信息,添加到订单备注 // if (data.tracking_number || data.shipping_provider) { // const note = `订单已发货${data.tracking_number ? `,物流单号:${data.tracking_number}` : ''}${data.shipping_provider ? `,物流公司:${data.shipping_provider}` : ''}`; // await api.post(`orders/${orderId}/notes`, { note, customer_note: true }); // } // return { // success: true, // order_id: orderId, // shipment_id: `shipment_${orderId}_${Date.now()}`, // tracking_number: data.tracking_number, // shipping_provider: data.shipping_provider, // shipped_at: new Date().toISOString() // }; // } catch (error) { // throw new Error(`发货失败: ${error.message}`); // } } async cancelShipOrder(orderId: string | number, data: { reason?: string; shipment_id?: string; }): Promise { throw new Error('暂未实现') // 取消订单发货 // const api = (this.wpService as any).createApi(this.site, 'wc/v3'); // try { // // 将订单状态改回处理中 // await api.put(`orders/${orderId}`, { status: 'processing' }); // // 添加取消发货的备注 // const note = `订单发货已取消${data.reason ? `,原因:${data.reason}` : ''}`; // await api.post(`orders/${orderId}/notes`, { note, customer_note: true }); // return { // success: true, // order_id: orderId, // shipment_id: data.shipment_id, // reason: data.reason, // cancelled_at: new Date().toISOString() // }; // } catch (error) { // throw new Error(`取消发货失败: ${error.message}`); // } } async getSubscriptions( params: UnifiedSearchParamsDTO ): Promise> { // 获取订阅列表并映射为统一订阅DTO集合 const { items, total, totalPages, page, per_page } = await this.wpService.fetchResourcePaged( this.site, 'subscriptions', params ); return { items: items.map(this.mapSubscription), total, totalPages, page, per_page, }; } async getMedia( params: UnifiedSearchParamsDTO ): Promise> { // 获取媒体列表并映射为统一媒体DTO集合 const { items, total, totalPages, page, per_page } = await this.wpService.fetchMediaPaged( this.site, params ); return { items: items.map(this.mapMedia.bind(this)), total, totalPages, page, per_page, }; } private mapReview(item: any): UnifiedReviewDTO & {raw: any} { // 将 WooCommerce 评论数据映射为统一评论DTO return { id: item.id, product_id: item.product_id, author: item.reviewer, email: item.reviewer_email, content: item.review, rating: item.rating, status: item.status, date_created: item.date_created, raw: item }; } async getReviews( params: UnifiedSearchParamsDTO ): Promise { // 获取评论列表并使用统一分页结构返回 const requestParams = this.mapProductSearchParams(params); const { items, total, totalPages, page, per_page } = await this.wpService.fetchResourcePaged( this.site, 'products/reviews', requestParams ); return { items: items.map(this.mapReview.bind(this)), total, totalPages, page, per_page, }; } async createReview(data: any): Promise { const res = await this.wpService.createReview(this.site, data); return this.mapReview(res); } async updateReview(id: number, data: any): Promise { const res = await this.wpService.updateReview(this.site, id, data); return this.mapReview(res); } async deleteReview(id: number): Promise { return await this.wpService.deleteReview(this.site, id); } async deleteMedia(id: string | number): Promise { // 删除媒体资源 await this.wpService.deleteMedia(Number(this.site.id), Number(id), true); return true; } async updateMedia(id: string | number, data: any): Promise { // 更新媒体信息 return await this.wpService.updateMedia(Number(this.site.id), Number(id), data); } async convertMediaToWebp(ids: Array): Promise<{ converted: any[]; failed: any[] }> { // 函数说明 调用服务层将站点的指定媒体批量转换为 webp 并上传 const result = await this.wpService.convertMediaToWebp(Number(this.site.id), ids); return result as any; } private mapCustomer(item: WooCustomer): UnifiedCustomerDTO { // 将 WooCommerce 客户数据映射为统一客户DTO // 包含基础信息地址信息与时间信息 return { id: item.id, avatar: item.avatar_url, email: item.email, orders: Number(item.orders?? 0), total_spend: Number(item.total_spent ?? 0), first_name: item.first_name, last_name: item.last_name, username: item.username, phone: item.billing?.phone || item.shipping?.phone, billing: item.billing, shipping: item.shipping, date_created: item.date_created, date_modified: item.date_modified, raw: item, }; } async getCustomers(params: UnifiedSearchParamsDTO): Promise> { const requestParams = this.mapCustomerSearchParams(params); const { items, total, totalPages, page, per_page } = await this.wpService.fetchResourcePaged( this.site, 'customers', requestParams ); return { items: items.map((i: any) => this.mapCustomer(i)), total, totalPages, page, per_page, }; } async getCustomer(id: string | number): Promise { const api = (this.wpService as any).createApi(this.site, 'wc/v3'); const res = await api.get(`customers/${id}`); return this.mapCustomer(res.data); } async createCustomer(data: Partial): Promise { const api = (this.wpService as any).createApi(this.site, 'wc/v3'); const res = await api.post('customers', data); return this.mapCustomer(res.data); } async updateCustomer(id: string | number, data: Partial): Promise { const api = (this.wpService as any).createApi(this.site, 'wc/v3'); const res = await api.put(`customers/${id}`, data); return this.mapCustomer(res.data); } async deleteCustomer(id: string | number): Promise { const api = (this.wpService as any).createApi(this.site, 'wc/v3'); await api.delete(`customers/${id}`, { force: true }); return true; } }