digital-tools 2.1.3 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +19 -0
- package/README.md +2 -0
- package/dist/client.d.ts +109 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +69 -0
- package/dist/client.js.map +1 -0
- package/dist/define.d.ts +2 -2
- package/dist/define.d.ts.map +1 -1
- package/dist/define.js +21 -11
- package/dist/define.js.map +1 -1
- package/dist/function-ref.d.ts +229 -0
- package/dist/function-ref.d.ts.map +1 -0
- package/dist/function-ref.js +28 -0
- package/dist/function-ref.js.map +1 -0
- package/dist/function-sugar.d.ts +57 -0
- package/dist/function-sugar.d.ts.map +1 -0
- package/dist/function-sugar.js +79 -0
- package/dist/function-sugar.js.map +1 -0
- package/dist/index.d.ts +10 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +24 -4
- package/dist/index.js.map +1 -1
- package/dist/providers/analytics/mixpanel.d.ts.map +1 -1
- package/dist/providers/analytics/mixpanel.js +21 -18
- package/dist/providers/analytics/mixpanel.js.map +1 -1
- package/dist/providers/calendar/cal-com.d.ts.map +1 -1
- package/dist/providers/calendar/cal-com.js +10 -10
- package/dist/providers/calendar/cal-com.js.map +1 -1
- package/dist/providers/calendar/google-calendar.d.ts.map +1 -1
- package/dist/providers/calendar/google-calendar.js +4 -4
- package/dist/providers/calendar/google-calendar.js.map +1 -1
- package/dist/providers/crm/hubspot.d.ts.map +1 -1
- package/dist/providers/crm/hubspot.js +107 -85
- package/dist/providers/crm/hubspot.js.map +1 -1
- package/dist/providers/development/github.d.ts.map +1 -1
- package/dist/providers/development/github.js +40 -43
- package/dist/providers/development/github.js.map +1 -1
- package/dist/providers/ecommerce/shopify.d.ts.map +1 -1
- package/dist/providers/ecommerce/shopify.js +79 -62
- package/dist/providers/ecommerce/shopify.js.map +1 -1
- package/dist/providers/email/resend.d.ts.map +1 -1
- package/dist/providers/email/resend.js +20 -16
- package/dist/providers/email/resend.js.map +1 -1
- package/dist/providers/email/sendgrid.d.ts.map +1 -1
- package/dist/providers/email/sendgrid.js +12 -9
- package/dist/providers/email/sendgrid.js.map +1 -1
- package/dist/providers/finance/stripe.d.ts.map +1 -1
- package/dist/providers/finance/stripe.js +44 -42
- package/dist/providers/finance/stripe.js.map +1 -1
- package/dist/providers/forms/typeform.d.ts.map +1 -1
- package/dist/providers/forms/typeform.js +68 -58
- package/dist/providers/forms/typeform.js.map +1 -1
- package/dist/providers/knowledge/notion.d.ts.map +1 -1
- package/dist/providers/knowledge/notion.js +75 -41
- package/dist/providers/knowledge/notion.js.map +1 -1
- package/dist/providers/marketing/mailchimp.d.ts.map +1 -1
- package/dist/providers/marketing/mailchimp.js +74 -61
- package/dist/providers/marketing/mailchimp.js.map +1 -1
- package/dist/providers/media/cloudinary.d.ts.map +1 -1
- package/dist/providers/media/cloudinary.js +30 -28
- package/dist/providers/media/cloudinary.js.map +1 -1
- package/dist/providers/messaging/slack.d.ts.map +1 -1
- package/dist/providers/messaging/slack.js +75 -58
- package/dist/providers/messaging/slack.js.map +1 -1
- package/dist/providers/messaging/twilio-sms.d.ts.map +1 -1
- package/dist/providers/messaging/twilio-sms.js +33 -15
- package/dist/providers/messaging/twilio-sms.js.map +1 -1
- package/dist/providers/project-management/linear.d.ts.map +1 -1
- package/dist/providers/project-management/linear.js +31 -27
- package/dist/providers/project-management/linear.js.map +1 -1
- package/dist/providers/spreadsheet/google-sheets.d.ts.map +1 -1
- package/dist/providers/spreadsheet/google-sheets.js +21 -18
- package/dist/providers/spreadsheet/google-sheets.js.map +1 -1
- package/dist/providers/spreadsheet/xlsx.d.ts.map +1 -1
- package/dist/providers/spreadsheet/xlsx.js +4 -4
- package/dist/providers/spreadsheet/xlsx.js.map +1 -1
- package/dist/providers/storage/index.js +1 -0
- package/dist/providers/storage/index.js.map +1 -1
- package/dist/providers/storage/s3.d.ts.map +1 -1
- package/dist/providers/storage/s3.js +36 -27
- package/dist/providers/storage/s3.js.map +1 -1
- package/dist/providers/support/zendesk.d.ts.map +1 -1
- package/dist/providers/support/zendesk.js +24 -25
- package/dist/providers/support/zendesk.js.map +1 -1
- package/dist/providers/tasks/todoist.d.ts.map +1 -1
- package/dist/providers/tasks/todoist.js +18 -18
- package/dist/providers/tasks/todoist.js.map +1 -1
- package/dist/providers/video-conferencing/google-meet.d.ts.map +1 -1
- package/dist/providers/video-conferencing/google-meet.js +11 -11
- package/dist/providers/video-conferencing/google-meet.js.map +1 -1
- package/dist/providers/video-conferencing/jitsi.js +14 -14
- package/dist/providers/video-conferencing/jitsi.js.map +1 -1
- package/dist/providers/video-conferencing/teams.d.ts.map +1 -1
- package/dist/providers/video-conferencing/teams.js +9 -7
- package/dist/providers/video-conferencing/teams.js.map +1 -1
- package/dist/providers/video-conferencing/zoom.d.ts.map +1 -1
- package/dist/providers/video-conferencing/zoom.js +26 -24
- package/dist/providers/video-conferencing/zoom.js.map +1 -1
- package/dist/tools/data.d.ts.map +1 -1
- package/dist/tools/data.js +5 -12
- package/dist/tools/data.js.map +1 -1
- package/dist/tools/index.d.ts +1 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +1 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/system.d.ts +289 -0
- package/dist/tools/system.d.ts.map +1 -0
- package/dist/tools/system.js +752 -0
- package/dist/tools/system.js.map +1 -0
- package/dist/tools/web.d.ts.map +1 -1
- package/dist/tools/web.js +22 -10
- package/dist/tools/web.js.map +1 -1
- package/dist/track-record.d.ts +101 -0
- package/dist/track-record.d.ts.map +1 -0
- package/dist/track-record.js +17 -0
- package/dist/track-record.js.map +1 -0
- package/dist/types.d.ts +210 -9
- package/dist/types.d.ts.map +1 -1
- package/dist/verb-registration.d.ts +122 -0
- package/dist/verb-registration.d.ts.map +1 -0
- package/dist/verb-registration.js +176 -0
- package/dist/verb-registration.js.map +1 -0
- package/dist/worker.d.ts +93 -0
- package/dist/worker.d.ts.map +1 -0
- package/dist/worker.js +315 -0
- package/dist/worker.js.map +1 -0
- package/dist/wrap.d.ts +89 -0
- package/dist/wrap.d.ts.map +1 -0
- package/dist/wrap.js +225 -0
- package/dist/wrap.js.map +1 -0
- package/package.json +31 -14
- package/src/client.ts +136 -0
- package/src/define.ts +30 -24
- package/src/function-ref.ts +264 -0
- package/src/function-sugar.ts +134 -0
- package/src/index.ts +132 -10
- package/src/providers/analytics/mixpanel.ts +19 -18
- package/src/providers/calendar/cal-com.ts +29 -18
- package/src/providers/calendar/google-calendar.ts +20 -14
- package/src/providers/crm/hubspot.ts +225 -99
- package/src/providers/development/github.ts +206 -135
- package/src/providers/ecommerce/shopify.ts +250 -89
- package/src/providers/email/resend.ts +101 -28
- package/src/providers/email/sendgrid.ts +12 -9
- package/src/providers/finance/stripe.ts +128 -49
- package/src/providers/forms/typeform.ts +74 -58
- package/src/providers/knowledge/notion.ts +340 -88
- package/src/providers/marketing/mailchimp.ts +86 -70
- package/src/providers/media/cloudinary.ts +99 -41
- package/src/providers/messaging/slack.ts +283 -85
- package/src/providers/messaging/twilio-sms.ts +35 -15
- package/src/providers/project-management/linear.ts +143 -55
- package/src/providers/spreadsheet/google-sheets.ts +222 -56
- package/src/providers/spreadsheet/xlsx.ts +47 -16
- package/src/providers/storage/s3.ts +119 -47
- package/src/providers/support/zendesk.ts +196 -46
- package/src/providers/tasks/todoist.ts +20 -26
- package/src/providers/video-conferencing/google-meet.ts +17 -20
- package/src/providers/video-conferencing/jitsi.ts +14 -14
- package/src/providers/video-conferencing/teams.ts +14 -13
- package/src/providers/video-conferencing/zoom.ts +54 -49
- package/src/tools/data.ts +6 -16
- package/src/tools/index.ts +1 -0
- package/src/tools/system.ts +887 -0
- package/src/tools/web.ts +22 -10
- package/src/track-record.ts +106 -0
- package/src/types.ts +241 -13
- package/src/verb-registration.ts +197 -0
- package/src/worker.ts +370 -0
- package/src/wrap.ts +260 -0
- package/test/client.test.ts +146 -0
- package/test/communication-tools-extended.test.ts +734 -0
- package/test/data-tools-extended.test.ts +743 -0
- package/test/define-extended.test.ts +819 -0
- package/test/define.test.ts +150 -41
- package/test/entities.test.ts +623 -0
- package/test/extended-entities.test.ts +1228 -0
- package/test/provider-implementations.test.ts +725 -0
- package/test/provider-registry-extended.test.ts +583 -0
- package/test/providers/google-sheets.test.ts +851 -0
- package/test/providers/helpers.ts +554 -0
- package/test/providers/hubspot.test.ts +576 -0
- package/test/providers/slack.test.ts +932 -0
- package/test/providers/stripe.test.ts +701 -0
- package/test/providers.test.ts +578 -0
- package/test/system-tools-extended.test.ts +632 -0
- package/test/system.test.ts +673 -0
- package/test/tools.test.ts +15 -11
- package/test/types.test.ts +402 -0
- package/test/verb-registration.test.ts +395 -0
- package/test/web-tools.test.ts +553 -0
- package/test/worker-extended.test.ts +699 -0
- package/test/worker.test.ts +576 -0
- package/test/wrap.test.ts +366 -0
- package/tsconfig.json +3 -13
- package/vitest.config.ts +37 -0
- package/wrangler.jsonc +9 -0
- package/LICENSE +0 -21
- package/dist/providers/voice/vapi.d.ts +0 -27
- package/dist/providers/voice/vapi.d.ts.map +0 -1
- package/dist/providers/voice/vapi.js +0 -440
- package/dist/providers/voice/vapi.js.map +0 -1
- package/src/define.js +0 -259
- package/src/entities/advertising.js +0 -999
- package/src/entities/ai.js +0 -756
- package/src/entities/analytics.js +0 -1588
- package/src/entities/automation.js +0 -601
- package/src/entities/communication.js +0 -1150
- package/src/entities/crm.js +0 -1386
- package/src/entities/design.js +0 -546
- package/src/entities/development.js +0 -2212
- package/src/entities/document.js +0 -874
- package/src/entities/ecommerce.js +0 -1429
- package/src/entities/experiment.js +0 -1039
- package/src/entities/finance.js +0 -3478
- package/src/entities/forms.js +0 -1892
- package/src/entities/hr.js +0 -661
- package/src/entities/identity.js +0 -997
- package/src/entities/index.js +0 -282
- package/src/entities/infrastructure.js +0 -1153
- package/src/entities/knowledge.js +0 -1438
- package/src/entities/marketing.js +0 -1610
- package/src/entities/media.js +0 -1634
- package/src/entities/notification.js +0 -1199
- package/src/entities/presentation.js +0 -1274
- package/src/entities/productivity.js +0 -1317
- package/src/entities/project-management.js +0 -1136
- package/src/entities/recruiting.js +0 -736
- package/src/entities/shipping.js +0 -509
- package/src/entities/signature.js +0 -1102
- package/src/entities/site.js +0 -222
- package/src/entities/spreadsheet.js +0 -1341
- package/src/entities/storage.js +0 -1198
- package/src/entities/support.js +0 -1166
- package/src/entities/video-conferencing.js +0 -1750
- package/src/entities/video.js +0 -950
- package/src/entities.js +0 -1663
- package/src/index.js +0 -74
- package/src/providers/analytics/index.js +0 -17
- package/src/providers/analytics/mixpanel.js +0 -255
- package/src/providers/calendar/cal-com.js +0 -303
- package/src/providers/calendar/google-calendar.js +0 -335
- package/src/providers/calendar/index.js +0 -20
- package/src/providers/crm/hubspot.js +0 -566
- package/src/providers/crm/index.js +0 -17
- package/src/providers/development/github.js +0 -472
- package/src/providers/development/index.js +0 -17
- package/src/providers/ecommerce/index.js +0 -17
- package/src/providers/ecommerce/shopify.js +0 -378
- package/src/providers/email/index.js +0 -20
- package/src/providers/email/resend.js +0 -258
- package/src/providers/email/sendgrid.js +0 -161
- package/src/providers/finance/index.js +0 -17
- package/src/providers/finance/stripe.js +0 -549
- package/src/providers/forms/index.js +0 -17
- package/src/providers/forms/typeform.js +0 -500
- package/src/providers/index.js +0 -123
- package/src/providers/knowledge/index.js +0 -17
- package/src/providers/knowledge/notion.js +0 -389
- package/src/providers/marketing/index.js +0 -17
- package/src/providers/marketing/mailchimp.js +0 -443
- package/src/providers/media/cloudinary.js +0 -318
- package/src/providers/media/index.js +0 -17
- package/src/providers/messaging/index.js +0 -20
- package/src/providers/messaging/slack.js +0 -393
- package/src/providers/messaging/twilio-sms.js +0 -249
- package/src/providers/project-management/index.js +0 -17
- package/src/providers/project-management/linear.js +0 -575
- package/src/providers/registry.js +0 -86
- package/src/providers/spreadsheet/google-sheets.js +0 -375
- package/src/providers/spreadsheet/index.js +0 -20
- package/src/providers/spreadsheet/xlsx.js +0 -423
- package/src/providers/storage/index.js +0 -24
- package/src/providers/storage/s3.js +0 -419
- package/src/providers/support/index.js +0 -17
- package/src/providers/support/zendesk.js +0 -373
- package/src/providers/tasks/index.js +0 -17
- package/src/providers/tasks/todoist.js +0 -286
- package/src/providers/types.js +0 -9
- package/src/providers/video-conferencing/google-meet.js +0 -286
- package/src/providers/video-conferencing/index.js +0 -31
- package/src/providers/video-conferencing/jitsi.js +0 -254
- package/src/providers/video-conferencing/teams.js +0 -270
- package/src/providers/video-conferencing/zoom.js +0 -332
- package/src/registry.js +0 -128
- package/src/tools/communication.js +0 -184
- package/src/tools/data.js +0 -205
- package/src/tools/index.js +0 -11
- package/src/tools/web.js +0 -137
- package/src/types.js +0 -10
- package/test/define.test.js +0 -306
- package/test/registry.test.js +0 -357
- package/test/tools.test.js +0 -363
|
@@ -24,6 +24,118 @@ import { defineProvider } from '../registry.js'
|
|
|
24
24
|
|
|
25
25
|
const API_VERSION = '2023-10'
|
|
26
26
|
|
|
27
|
+
// =============================================================================
|
|
28
|
+
// Shopify API Response Types
|
|
29
|
+
// =============================================================================
|
|
30
|
+
|
|
31
|
+
/** Shopify API error response */
|
|
32
|
+
interface ShopifyErrorResponse {
|
|
33
|
+
errors?: string | Record<string, string[]>
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Shopify product image from API */
|
|
37
|
+
interface ShopifyImage {
|
|
38
|
+
id: number
|
|
39
|
+
src: string
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Shopify product variant from API */
|
|
43
|
+
interface ShopifyVariant {
|
|
44
|
+
id: number
|
|
45
|
+
title: string
|
|
46
|
+
price: string
|
|
47
|
+
sku?: string
|
|
48
|
+
inventory_quantity: number
|
|
49
|
+
compare_at_price?: string | null
|
|
50
|
+
inventory_item_id: number
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Shopify product from API */
|
|
54
|
+
interface ShopifyProduct {
|
|
55
|
+
id: number
|
|
56
|
+
title: string
|
|
57
|
+
body_html?: string
|
|
58
|
+
vendor?: string
|
|
59
|
+
product_type?: string
|
|
60
|
+
tags?: string
|
|
61
|
+
status?: string
|
|
62
|
+
variants?: ShopifyVariant[]
|
|
63
|
+
images?: ShopifyImage[]
|
|
64
|
+
admin_graphql_api_id?: string
|
|
65
|
+
created_at: string
|
|
66
|
+
updated_at: string
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Shopify address from API */
|
|
70
|
+
interface ShopifyAddress {
|
|
71
|
+
first_name?: string
|
|
72
|
+
last_name?: string
|
|
73
|
+
address1?: string
|
|
74
|
+
address2?: string
|
|
75
|
+
city?: string
|
|
76
|
+
province?: string
|
|
77
|
+
zip?: string
|
|
78
|
+
country?: string
|
|
79
|
+
phone?: string
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** Shopify line item from API */
|
|
83
|
+
interface ShopifyLineItem {
|
|
84
|
+
product_id?: number
|
|
85
|
+
variant_id?: number
|
|
86
|
+
title: string
|
|
87
|
+
quantity: number
|
|
88
|
+
price: string
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** Shopify customer reference from API */
|
|
92
|
+
interface ShopifyOrderCustomer {
|
|
93
|
+
id?: number
|
|
94
|
+
email?: string
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** Shopify order from API */
|
|
98
|
+
interface ShopifyOrder {
|
|
99
|
+
id: number
|
|
100
|
+
name?: string
|
|
101
|
+
order_number?: number
|
|
102
|
+
cancelled_at?: string | null
|
|
103
|
+
closed_at?: string | null
|
|
104
|
+
financial_status?: string
|
|
105
|
+
fulfillment_status?: string | null
|
|
106
|
+
customer?: ShopifyOrderCustomer
|
|
107
|
+
email?: string
|
|
108
|
+
line_items?: ShopifyLineItem[]
|
|
109
|
+
subtotal_price?: string
|
|
110
|
+
total_tax?: string
|
|
111
|
+
total_shipping_price_set?: { shop_money?: { amount?: string } }
|
|
112
|
+
total_price?: string
|
|
113
|
+
currency?: string
|
|
114
|
+
shipping_address?: ShopifyAddress
|
|
115
|
+
billing_address?: ShopifyAddress
|
|
116
|
+
created_at: string
|
|
117
|
+
updated_at: string
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** Shopify customer from API */
|
|
121
|
+
interface ShopifyCustomer {
|
|
122
|
+
id: number
|
|
123
|
+
email?: string
|
|
124
|
+
first_name?: string
|
|
125
|
+
last_name?: string
|
|
126
|
+
phone?: string
|
|
127
|
+
orders_count?: number
|
|
128
|
+
total_spent?: string
|
|
129
|
+
created_at: string
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/** Shopify inventory level from API */
|
|
133
|
+
interface ShopifyInventoryLevel {
|
|
134
|
+
location_id: number
|
|
135
|
+
inventory_item_id: number
|
|
136
|
+
available: number
|
|
137
|
+
}
|
|
138
|
+
|
|
27
139
|
/**
|
|
28
140
|
* Shopify provider info
|
|
29
141
|
*/
|
|
@@ -61,14 +173,18 @@ export function createShopifyProvider(config: ProviderConfig): EcommerceProvider
|
|
|
61
173
|
const response = await fetch(`${baseUrl}${endpoint}`, {
|
|
62
174
|
method,
|
|
63
175
|
headers: getHeaders(),
|
|
64
|
-
body
|
|
176
|
+
...(body !== undefined && { body: JSON.stringify(body) }),
|
|
65
177
|
})
|
|
66
178
|
|
|
67
179
|
if (!response.ok) {
|
|
68
|
-
const errorData = await response.json().catch(() => ({}))
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
180
|
+
const errorData = (await response.json().catch(() => ({}))) as ShopifyErrorResponse
|
|
181
|
+
const errorMessage =
|
|
182
|
+
typeof errorData.errors === 'string'
|
|
183
|
+
? errorData.errors
|
|
184
|
+
: errorData.errors
|
|
185
|
+
? JSON.stringify(errorData.errors)
|
|
186
|
+
: response.statusText
|
|
187
|
+
throw new Error(`Shopify API error: ${response.status} - ${errorMessage}`)
|
|
72
188
|
}
|
|
73
189
|
|
|
74
190
|
return response.json() as Promise<T>
|
|
@@ -78,8 +194,8 @@ export function createShopifyProvider(config: ProviderConfig): EcommerceProvider
|
|
|
78
194
|
info: shopifyInfo,
|
|
79
195
|
|
|
80
196
|
async initialize(cfg: ProviderConfig): Promise<void> {
|
|
81
|
-
shopDomain = cfg
|
|
82
|
-
accessToken = cfg
|
|
197
|
+
shopDomain = cfg['shopDomain'] as string
|
|
198
|
+
accessToken = cfg['accessToken'] as string
|
|
83
199
|
|
|
84
200
|
if (!shopDomain) {
|
|
85
201
|
throw new Error('Shopify shop domain is required')
|
|
@@ -122,13 +238,23 @@ export function createShopifyProvider(config: ProviderConfig): EcommerceProvider
|
|
|
122
238
|
},
|
|
123
239
|
|
|
124
240
|
async createProduct(product: CreateProductOptions): Promise<EcommerceProductData> {
|
|
125
|
-
const shopifyProduct:
|
|
241
|
+
const shopifyProduct: {
|
|
242
|
+
title: string
|
|
243
|
+
body_html?: string
|
|
244
|
+
vendor: string
|
|
245
|
+
product_type: string
|
|
246
|
+
tags: string
|
|
247
|
+
status: string
|
|
248
|
+
variants: Array<{ title: string; price: string; sku?: string; inventory_quantity: number }>
|
|
249
|
+
images?: Array<{ src: string }>
|
|
250
|
+
} = {
|
|
126
251
|
title: product.title,
|
|
127
|
-
body_html: product.description,
|
|
252
|
+
...(product.description !== undefined && { body_html: product.description }),
|
|
128
253
|
vendor: 'Default',
|
|
129
254
|
product_type: '',
|
|
130
255
|
tags: product.tags?.join(', ') || '',
|
|
131
256
|
status: product.status || 'active',
|
|
257
|
+
variants: [],
|
|
132
258
|
}
|
|
133
259
|
|
|
134
260
|
// Add variants
|
|
@@ -136,7 +262,7 @@ export function createShopifyProvider(config: ProviderConfig): EcommerceProvider
|
|
|
136
262
|
shopifyProduct.variants = product.variants.map((v) => ({
|
|
137
263
|
title: v.title,
|
|
138
264
|
price: v.price.toString(),
|
|
139
|
-
sku: v.sku,
|
|
265
|
+
...(v.sku !== undefined && { sku: v.sku }),
|
|
140
266
|
inventory_quantity: v.inventory || 0,
|
|
141
267
|
}))
|
|
142
268
|
} else {
|
|
@@ -145,7 +271,7 @@ export function createShopifyProvider(config: ProviderConfig): EcommerceProvider
|
|
|
145
271
|
{
|
|
146
272
|
title: 'Default Title',
|
|
147
273
|
price: product.price.toString(),
|
|
148
|
-
sku: product.sku,
|
|
274
|
+
...(product.sku !== undefined && { sku: product.sku }),
|
|
149
275
|
inventory_quantity: product.inventory || 0,
|
|
150
276
|
},
|
|
151
277
|
]
|
|
@@ -156,7 +282,7 @@ export function createShopifyProvider(config: ProviderConfig): EcommerceProvider
|
|
|
156
282
|
shopifyProduct.images = product.images.map((url) => ({ src: url }))
|
|
157
283
|
}
|
|
158
284
|
|
|
159
|
-
const response = await makeRequest<{ product:
|
|
285
|
+
const response = await makeRequest<{ product: ShopifyProduct }>('/products.json', 'POST', {
|
|
160
286
|
product: shopifyProduct,
|
|
161
287
|
})
|
|
162
288
|
|
|
@@ -165,9 +291,12 @@ export function createShopifyProvider(config: ProviderConfig): EcommerceProvider
|
|
|
165
291
|
|
|
166
292
|
async getProduct(productId: string): Promise<EcommerceProductData | null> {
|
|
167
293
|
try {
|
|
168
|
-
const response = await makeRequest<{ product:
|
|
294
|
+
const response = await makeRequest<{ product: ShopifyProduct }>(
|
|
295
|
+
`/products/${productId}.json`,
|
|
296
|
+
'GET'
|
|
297
|
+
)
|
|
169
298
|
return mapShopifyProduct(response.product)
|
|
170
|
-
} catch
|
|
299
|
+
} catch {
|
|
171
300
|
return null
|
|
172
301
|
}
|
|
173
302
|
},
|
|
@@ -176,7 +305,13 @@ export function createShopifyProvider(config: ProviderConfig): EcommerceProvider
|
|
|
176
305
|
productId: string,
|
|
177
306
|
updates: Partial<CreateProductOptions>
|
|
178
307
|
): Promise<EcommerceProductData> {
|
|
179
|
-
const shopifyUpdates:
|
|
308
|
+
const shopifyUpdates: {
|
|
309
|
+
title?: string
|
|
310
|
+
body_html?: string
|
|
311
|
+
tags?: string
|
|
312
|
+
status?: string
|
|
313
|
+
images?: Array<{ src: string }>
|
|
314
|
+
} = {}
|
|
180
315
|
|
|
181
316
|
if (updates.title) shopifyUpdates.title = updates.title
|
|
182
317
|
if (updates.description) shopifyUpdates.body_html = updates.description
|
|
@@ -188,9 +323,13 @@ export function createShopifyProvider(config: ProviderConfig): EcommerceProvider
|
|
|
188
323
|
shopifyUpdates.images = updates.images.map((url) => ({ src: url }))
|
|
189
324
|
}
|
|
190
325
|
|
|
191
|
-
const response = await makeRequest<{ product:
|
|
192
|
-
|
|
193
|
-
|
|
326
|
+
const response = await makeRequest<{ product: ShopifyProduct }>(
|
|
327
|
+
`/products/${productId}.json`,
|
|
328
|
+
'PUT',
|
|
329
|
+
{
|
|
330
|
+
product: shopifyUpdates,
|
|
331
|
+
}
|
|
332
|
+
)
|
|
194
333
|
|
|
195
334
|
return mapShopifyProduct(response.product)
|
|
196
335
|
},
|
|
@@ -199,12 +338,14 @@ export function createShopifyProvider(config: ProviderConfig): EcommerceProvider
|
|
|
199
338
|
try {
|
|
200
339
|
await makeRequest(`/products/${productId}.json`, 'DELETE')
|
|
201
340
|
return true
|
|
202
|
-
} catch
|
|
341
|
+
} catch {
|
|
203
342
|
return false
|
|
204
343
|
}
|
|
205
344
|
},
|
|
206
345
|
|
|
207
|
-
async listProducts(
|
|
346
|
+
async listProducts(
|
|
347
|
+
options?: ProductListOptions
|
|
348
|
+
): Promise<PaginatedResult<EcommerceProductData>> {
|
|
208
349
|
const params = new URLSearchParams()
|
|
209
350
|
|
|
210
351
|
if (options?.limit) params.append('limit', options.limit.toString())
|
|
@@ -215,20 +356,22 @@ export function createShopifyProvider(config: ProviderConfig): EcommerceProvider
|
|
|
215
356
|
const queryString = params.toString()
|
|
216
357
|
const endpoint = `/products.json${queryString ? `?${queryString}` : ''}`
|
|
217
358
|
|
|
218
|
-
const response = await makeRequest<{ products:
|
|
359
|
+
const response = await makeRequest<{ products: ShopifyProduct[] }>(endpoint, 'GET')
|
|
219
360
|
|
|
220
361
|
return {
|
|
221
362
|
items: response.products.map(mapShopifyProduct),
|
|
222
363
|
hasMore: response.products.length === (options?.limit || 50),
|
|
223
|
-
total: undefined, // Shopify doesn't provide total count in products endpoint
|
|
224
364
|
}
|
|
225
365
|
},
|
|
226
366
|
|
|
227
367
|
async getOrder(orderId: string): Promise<OrderData | null> {
|
|
228
368
|
try {
|
|
229
|
-
const response = await makeRequest<{ order:
|
|
369
|
+
const response = await makeRequest<{ order: ShopifyOrder }>(
|
|
370
|
+
`/orders/${orderId}.json`,
|
|
371
|
+
'GET'
|
|
372
|
+
)
|
|
230
373
|
return mapShopifyOrder(response.order)
|
|
231
|
-
} catch
|
|
374
|
+
} catch {
|
|
232
375
|
return null
|
|
233
376
|
}
|
|
234
377
|
},
|
|
@@ -239,8 +382,7 @@ export function createShopifyProvider(config: ProviderConfig): EcommerceProvider
|
|
|
239
382
|
if (options?.limit) params.append('limit', options.limit.toString())
|
|
240
383
|
if (options?.status) params.append('status', options.status)
|
|
241
384
|
if (options?.financialStatus) params.append('financial_status', options.financialStatus)
|
|
242
|
-
if (options?.fulfillmentStatus)
|
|
243
|
-
params.append('fulfillment_status', options.fulfillmentStatus)
|
|
385
|
+
if (options?.fulfillmentStatus) params.append('fulfillment_status', options.fulfillmentStatus)
|
|
244
386
|
if (options?.customerId) params.append('customer_id', options.customerId)
|
|
245
387
|
if (options?.since) params.append('created_at_min', options.since.toISOString())
|
|
246
388
|
if (options?.until) params.append('created_at_max', options.until.toISOString())
|
|
@@ -249,31 +391,37 @@ export function createShopifyProvider(config: ProviderConfig): EcommerceProvider
|
|
|
249
391
|
const queryString = params.toString()
|
|
250
392
|
const endpoint = `/orders.json${queryString ? `?${queryString}` : ''}`
|
|
251
393
|
|
|
252
|
-
const response = await makeRequest<{ orders:
|
|
394
|
+
const response = await makeRequest<{ orders: ShopifyOrder[] }>(endpoint, 'GET')
|
|
253
395
|
|
|
254
396
|
return {
|
|
255
397
|
items: response.orders.map(mapShopifyOrder),
|
|
256
398
|
hasMore: response.orders.length === (options?.limit || 50),
|
|
257
|
-
total: undefined,
|
|
258
399
|
}
|
|
259
400
|
},
|
|
260
401
|
|
|
261
402
|
async updateOrderStatus(orderId: string, status: string): Promise<OrderData> {
|
|
262
|
-
const response = await makeRequest<{ order:
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
403
|
+
const response = await makeRequest<{ order: ShopifyOrder }>(
|
|
404
|
+
`/orders/${orderId}.json`,
|
|
405
|
+
'PUT',
|
|
406
|
+
{
|
|
407
|
+
order: {
|
|
408
|
+
id: orderId,
|
|
409
|
+
tags: status,
|
|
410
|
+
},
|
|
411
|
+
}
|
|
412
|
+
)
|
|
268
413
|
|
|
269
414
|
return mapShopifyOrder(response.order)
|
|
270
415
|
},
|
|
271
416
|
|
|
272
417
|
async getEcommerceCustomer(customerId: string): Promise<EcommerceCustomerData | null> {
|
|
273
418
|
try {
|
|
274
|
-
const response = await makeRequest<{ customer:
|
|
419
|
+
const response = await makeRequest<{ customer: ShopifyCustomer }>(
|
|
420
|
+
`/customers/${customerId}.json`,
|
|
421
|
+
'GET'
|
|
422
|
+
)
|
|
275
423
|
return mapShopifyCustomer(response.customer)
|
|
276
|
-
} catch
|
|
424
|
+
} catch {
|
|
277
425
|
return null
|
|
278
426
|
}
|
|
279
427
|
},
|
|
@@ -289,30 +437,29 @@ export function createShopifyProvider(config: ProviderConfig): EcommerceProvider
|
|
|
289
437
|
const queryString = params.toString()
|
|
290
438
|
const endpoint = `/customers.json${queryString ? `?${queryString}` : ''}`
|
|
291
439
|
|
|
292
|
-
const response = await makeRequest<{ customers:
|
|
440
|
+
const response = await makeRequest<{ customers: ShopifyCustomer[] }>(endpoint, 'GET')
|
|
293
441
|
|
|
294
442
|
return {
|
|
295
443
|
items: response.customers.map(mapShopifyCustomer),
|
|
296
444
|
hasMore: response.customers.length === (options?.limit || 50),
|
|
297
|
-
total: undefined,
|
|
298
445
|
}
|
|
299
446
|
},
|
|
300
447
|
|
|
301
448
|
async updateInventory(
|
|
302
|
-
|
|
449
|
+
_productId: string,
|
|
303
450
|
variantId: string,
|
|
304
451
|
quantity: number
|
|
305
452
|
): Promise<boolean> {
|
|
306
453
|
try {
|
|
307
454
|
// First get the inventory item ID from the variant
|
|
308
|
-
const variantResponse = await makeRequest<{ variant:
|
|
455
|
+
const variantResponse = await makeRequest<{ variant: ShopifyVariant }>(
|
|
309
456
|
`/variants/${variantId}.json`,
|
|
310
457
|
'GET'
|
|
311
458
|
)
|
|
312
459
|
const inventoryItemId = variantResponse.variant.inventory_item_id
|
|
313
460
|
|
|
314
461
|
// Get inventory levels
|
|
315
|
-
const levelsResponse = await makeRequest<{ inventory_levels:
|
|
462
|
+
const levelsResponse = await makeRequest<{ inventory_levels: ShopifyInventoryLevel[] }>(
|
|
316
463
|
`/inventory_levels.json?inventory_item_ids=${inventoryItemId}`,
|
|
317
464
|
'GET'
|
|
318
465
|
)
|
|
@@ -321,7 +468,11 @@ export function createShopifyProvider(config: ProviderConfig): EcommerceProvider
|
|
|
321
468
|
throw new Error('No inventory levels found for this variant')
|
|
322
469
|
}
|
|
323
470
|
|
|
324
|
-
const
|
|
471
|
+
const firstLevel = levelsResponse.inventory_levels[0]
|
|
472
|
+
if (!firstLevel) {
|
|
473
|
+
throw new Error('No inventory levels found for this variant')
|
|
474
|
+
}
|
|
475
|
+
const locationId = firstLevel.location_id
|
|
325
476
|
|
|
326
477
|
// Set the inventory level
|
|
327
478
|
await makeRequest('/inventory_levels/set.json', 'POST', {
|
|
@@ -331,7 +482,7 @@ export function createShopifyProvider(config: ProviderConfig): EcommerceProvider
|
|
|
331
482
|
})
|
|
332
483
|
|
|
333
484
|
return true
|
|
334
|
-
} catch
|
|
485
|
+
} catch {
|
|
335
486
|
return false
|
|
336
487
|
}
|
|
337
488
|
},
|
|
@@ -341,31 +492,33 @@ export function createShopifyProvider(config: ProviderConfig): EcommerceProvider
|
|
|
341
492
|
/**
|
|
342
493
|
* Map Shopify product to our format
|
|
343
494
|
*/
|
|
344
|
-
function mapShopifyProduct(product:
|
|
495
|
+
function mapShopifyProduct(product: ShopifyProduct): EcommerceProductData {
|
|
345
496
|
const firstVariant = product.variants?.[0]
|
|
346
497
|
|
|
347
498
|
return {
|
|
348
499
|
id: product.id.toString(),
|
|
349
500
|
title: product.title,
|
|
350
|
-
description: product.body_html,
|
|
501
|
+
...(product.body_html !== undefined && { description: product.body_html }),
|
|
351
502
|
price: parseFloat(firstVariant?.price || '0'),
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
sku: firstVariant
|
|
356
|
-
|
|
357
|
-
|
|
503
|
+
...(firstVariant?.compare_at_price && {
|
|
504
|
+
compareAtPrice: parseFloat(firstVariant.compare_at_price),
|
|
505
|
+
}),
|
|
506
|
+
...(firstVariant?.sku !== undefined && { sku: firstVariant.sku }),
|
|
507
|
+
...(firstVariant?.inventory_quantity !== undefined && {
|
|
508
|
+
inventory: firstVariant.inventory_quantity,
|
|
509
|
+
}),
|
|
510
|
+
images: product.images?.map((img) => img.src) || [],
|
|
358
511
|
variants:
|
|
359
|
-
product.variants?.map((v
|
|
512
|
+
product.variants?.map((v) => ({
|
|
360
513
|
id: v.id.toString(),
|
|
361
514
|
title: v.title,
|
|
362
515
|
price: parseFloat(v.price),
|
|
363
|
-
sku: v.sku,
|
|
516
|
+
...(v.sku !== undefined && { sku: v.sku }),
|
|
364
517
|
inventory: v.inventory_quantity,
|
|
365
518
|
})) || [],
|
|
366
519
|
tags: product.tags ? product.tags.split(', ') : [],
|
|
367
|
-
status: product.status,
|
|
368
|
-
url: product.admin_graphql_api_id,
|
|
520
|
+
status: product.status || 'active',
|
|
521
|
+
...(product.admin_graphql_api_id !== undefined && { url: product.admin_graphql_api_id }),
|
|
369
522
|
createdAt: new Date(product.created_at),
|
|
370
523
|
updatedAt: new Date(product.updated_at),
|
|
371
524
|
}
|
|
@@ -374,19 +527,19 @@ function mapShopifyProduct(product: any): EcommerceProductData {
|
|
|
374
527
|
/**
|
|
375
528
|
* Map Shopify order to our format
|
|
376
529
|
*/
|
|
377
|
-
function mapShopifyOrder(order:
|
|
530
|
+
function mapShopifyOrder(order: ShopifyOrder): OrderData {
|
|
378
531
|
return {
|
|
379
532
|
id: order.id.toString(),
|
|
380
|
-
orderNumber: order.name || order.order_number?.toString(),
|
|
533
|
+
orderNumber: order.name || order.order_number?.toString() || '',
|
|
381
534
|
status: order.cancelled_at ? 'cancelled' : order.closed_at ? 'closed' : 'open',
|
|
382
|
-
financialStatus: order.financial_status,
|
|
535
|
+
financialStatus: order.financial_status || 'pending',
|
|
383
536
|
fulfillmentStatus: order.fulfillment_status || 'unfulfilled',
|
|
384
|
-
customerId: order.customer
|
|
537
|
+
...(order.customer?.id !== undefined && { customerId: order.customer.id.toString() }),
|
|
385
538
|
email: order.email || order.customer?.email || '',
|
|
386
539
|
lineItems:
|
|
387
|
-
order.line_items?.map((item
|
|
540
|
+
order.line_items?.map((item) => ({
|
|
388
541
|
productId: item.product_id?.toString() || '',
|
|
389
|
-
variantId: item.variant_id
|
|
542
|
+
...(item.variant_id !== undefined && { variantId: item.variant_id.toString() }),
|
|
390
543
|
title: item.title,
|
|
391
544
|
quantity: item.quantity,
|
|
392
545
|
price: parseFloat(item.price),
|
|
@@ -395,33 +548,41 @@ function mapShopifyOrder(order: any): OrderData {
|
|
|
395
548
|
tax: parseFloat(order.total_tax || '0'),
|
|
396
549
|
shipping: parseFloat(order.total_shipping_price_set?.shop_money?.amount || '0'),
|
|
397
550
|
total: parseFloat(order.total_price || '0'),
|
|
398
|
-
currency: order.currency,
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
551
|
+
currency: order.currency || 'USD',
|
|
552
|
+
...(order.shipping_address && {
|
|
553
|
+
shippingAddress: {
|
|
554
|
+
firstName: order.shipping_address.first_name || '',
|
|
555
|
+
lastName: order.shipping_address.last_name || '',
|
|
556
|
+
address1: order.shipping_address.address1 || '',
|
|
557
|
+
...(order.shipping_address.address2 !== undefined && {
|
|
404
558
|
address2: order.shipping_address.address2,
|
|
405
|
-
|
|
559
|
+
}),
|
|
560
|
+
city: order.shipping_address.city || '',
|
|
561
|
+
...(order.shipping_address.province !== undefined && {
|
|
406
562
|
province: order.shipping_address.province,
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
563
|
+
}),
|
|
564
|
+
postalCode: order.shipping_address.zip || '',
|
|
565
|
+
country: order.shipping_address.country || '',
|
|
566
|
+
...(order.shipping_address.phone !== undefined && { phone: order.shipping_address.phone }),
|
|
567
|
+
},
|
|
568
|
+
}),
|
|
569
|
+
...(order.billing_address && {
|
|
570
|
+
billingAddress: {
|
|
571
|
+
firstName: order.billing_address.first_name || '',
|
|
572
|
+
lastName: order.billing_address.last_name || '',
|
|
573
|
+
address1: order.billing_address.address1 || '',
|
|
574
|
+
...(order.billing_address.address2 !== undefined && {
|
|
417
575
|
address2: order.billing_address.address2,
|
|
418
|
-
|
|
576
|
+
}),
|
|
577
|
+
city: order.billing_address.city || '',
|
|
578
|
+
...(order.billing_address.province !== undefined && {
|
|
419
579
|
province: order.billing_address.province,
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
}
|
|
424
|
-
|
|
580
|
+
}),
|
|
581
|
+
postalCode: order.billing_address.zip || '',
|
|
582
|
+
country: order.billing_address.country || '',
|
|
583
|
+
...(order.billing_address.phone !== undefined && { phone: order.billing_address.phone }),
|
|
584
|
+
},
|
|
585
|
+
}),
|
|
425
586
|
createdAt: new Date(order.created_at),
|
|
426
587
|
updatedAt: new Date(order.updated_at),
|
|
427
588
|
}
|
|
@@ -430,13 +591,13 @@ function mapShopifyOrder(order: any): OrderData {
|
|
|
430
591
|
/**
|
|
431
592
|
* Map Shopify customer to our format
|
|
432
593
|
*/
|
|
433
|
-
function mapShopifyCustomer(customer:
|
|
594
|
+
function mapShopifyCustomer(customer: ShopifyCustomer): EcommerceCustomerData {
|
|
434
595
|
return {
|
|
435
596
|
id: customer.id.toString(),
|
|
436
|
-
email: customer.email,
|
|
437
|
-
firstName: customer.first_name,
|
|
438
|
-
lastName: customer.last_name,
|
|
439
|
-
phone: customer.phone,
|
|
597
|
+
email: customer.email || '',
|
|
598
|
+
...(customer.first_name !== undefined && { firstName: customer.first_name }),
|
|
599
|
+
...(customer.last_name !== undefined && { lastName: customer.last_name }),
|
|
600
|
+
...(customer.phone !== undefined && { phone: customer.phone }),
|
|
440
601
|
ordersCount: customer.orders_count || 0,
|
|
441
602
|
totalSpent: parseFloat(customer.total_spent || '0'),
|
|
442
603
|
createdAt: new Date(customer.created_at),
|