@ehrenkind/shopify-lib 0.4.1 → 0.5.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/dist/index.cjs CHANGED
@@ -31,19 +31,32 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
33
  ShopifyUserError: () => ShopifyUserError,
34
+ bulkUpdateProductVariants: () => bulkUpdateProductVariants,
35
+ calculateRefund: () => calculateRefund,
34
36
  cancelOrderById: () => cancelOrderById,
37
+ createFile: () => createFile,
38
+ createFulfillment: () => createFulfillment,
39
+ createMetaobjectDefinition: () => createMetaobjectDefinition,
40
+ createRefund: () => createRefund,
35
41
  deleteCustomerById: () => deleteCustomerById,
42
+ deleteFilesByIds: () => deleteFilesByIds,
43
+ getAllProductVariants: () => getAllProductVariants,
44
+ getCustomerSegmentMembers: () => getCustomerSegmentMembers,
36
45
  getCustomersByEmail: () => getCustomersByEmail,
37
46
  getFulfillmentById: () => getFulfillmentById,
38
47
  getFulfillmentOrdersByOrderId: () => getFulfillmentOrdersByOrderId,
39
48
  getFulfillmentTrackingIds: () => getFulfillmentTrackingIds,
40
49
  getLeanProductVariants: () => getLeanProductVariants,
50
+ getMetaobjectByHandle: () => getMetaobjectByHandle,
41
51
  getOrderById: () => getOrderById,
42
52
  getOrderByName: () => getOrderByName,
43
53
  getOrderCancellationInfoByName: () => getOrderCancellationInfoByName,
44
54
  getOrderPaymentDetailsById: () => getOrderPaymentDetailsById,
45
55
  getOrdersByCustomerId: () => getOrdersByCustomerId,
46
- parseGid: () => parseGid
56
+ getProductVariantsBySkus: () => getProductVariantsBySkus,
57
+ parseGid: () => parseGid,
58
+ updateFulfillmentTracking: () => updateFulfillmentTracking,
59
+ upsertMetaobject: () => upsertMetaobject
47
60
  });
48
61
  module.exports = __toCommonJS(index_exports);
49
62
 
@@ -248,7 +261,7 @@ async function makeRequest(query, variables) {
248
261
 
249
262
  // src/mutations/customers/deleteCustomerById.ts
250
263
  async function deleteCustomerById(customerId) {
251
- const mutation2 = gql`#graphql
264
+ const mutation9 = gql`#graphql
252
265
  mutation customerDelete($input: CustomerDeleteInput!) {
253
266
  customerDelete(input: $input) {
254
267
  deletedCustomerId
@@ -263,7 +276,7 @@ async function deleteCustomerById(customerId) {
263
276
  input: { id: customerId }
264
277
  };
265
278
  const response = await fetchShopifyGraphql({
266
- query: mutation2,
279
+ query: mutation9,
267
280
  variables,
268
281
  dataExtractor: (data) => {
269
282
  if (!data.customerDelete) {
@@ -277,11 +290,368 @@ async function deleteCustomerById(customerId) {
277
290
  };
278
291
  }
279
292
  });
280
- return response[0]?.deletedCustomerId ?? null;
293
+ return response[0]?.deletedCustomerId ?? void 0;
281
294
  }
282
295
 
283
- // src/mutations/orders/cancelOrderById.ts
296
+ // src/mutations/files/deleteFilesByIds.ts
297
+ async function deleteFilesByIds(fileIds) {
298
+ if (fileIds.length === 0) {
299
+ return [];
300
+ }
301
+ const mutation9 = gql`#graphql
302
+ mutation fileDelete($fileIds: [ID!]!) {
303
+ fileDelete(fileIds: $fileIds) {
304
+ deletedFileIds
305
+ userErrors {
306
+ code
307
+ field
308
+ message
309
+ }
310
+ }
311
+ }
312
+ `;
313
+ const variables = { fileIds };
314
+ const response = await fetchShopifyGraphql({
315
+ query: mutation9,
316
+ variables,
317
+ dataExtractor: (data) => {
318
+ if (!data.fileDelete) {
319
+ throw new Error("GraphQL response missing 'fileDelete' field");
320
+ }
321
+ return {
322
+ nodes: [{ deletedFileIds: data.fileDelete.deletedFileIds ?? [] }],
323
+ userErrors: data.fileDelete.userErrors
324
+ };
325
+ }
326
+ });
327
+ return response[0]?.deletedFileIds ?? [];
328
+ }
329
+
330
+ // src/mutations/files/createFile.ts
284
331
  var mutation = gql`#graphql
332
+ mutation createFile($files: [FileCreateInput!]!) {
333
+ fileCreate(files: $files) {
334
+ files {
335
+ id
336
+ }
337
+ userErrors {
338
+ code
339
+ field
340
+ message
341
+ }
342
+ }
343
+ }
344
+ `;
345
+ async function createFile(url, altText, filename) {
346
+ if (!url.startsWith("https://")) {
347
+ throw new Error(
348
+ `Not a valid public URL (https://) provided for file (url: ${url}).`
349
+ );
350
+ }
351
+ logger.debug(`Creating file: ${filename}`);
352
+ const variables = {
353
+ files: [
354
+ {
355
+ originalSource: url,
356
+ alt: altText,
357
+ filename
358
+ }
359
+ ]
360
+ };
361
+ const result = await fetchShopifyGraphql({
362
+ query: mutation,
363
+ variables,
364
+ dataExtractor: (data) => {
365
+ if (!data.fileCreate) {
366
+ throw new Error("GraphQL response missing 'fileCreate' field");
367
+ }
368
+ const file = data.fileCreate.files?.[0];
369
+ return {
370
+ nodes: file ? [{ id: file.id }] : [],
371
+ userErrors: data.fileCreate.userErrors
372
+ };
373
+ }
374
+ });
375
+ const fileId = result[0]?.id;
376
+ if (!fileId) {
377
+ throw new Error("File creation returned no result");
378
+ }
379
+ logger.debug(`Successfully created file ${fileId}`);
380
+ return fileId;
381
+ }
382
+
383
+ // src/mutations/metaobjectDefinitions/createMetaobjectDefinition.ts
384
+ var mutation2 = gql`#graphql
385
+ mutation createMetaobjectDefinition($definition: MetaobjectDefinitionCreateInput!) {
386
+ metaobjectDefinitionCreate(definition: $definition) {
387
+ metaobjectDefinition {
388
+ id
389
+ name
390
+ type
391
+ }
392
+ userErrors {
393
+ code
394
+ field
395
+ message
396
+ }
397
+ }
398
+ }
399
+ `;
400
+ async function createMetaobjectDefinition(input) {
401
+ logger.debug(`Creating metaobject definition with type: ${input.type}`);
402
+ const variables = {
403
+ definition: {
404
+ type: input.type,
405
+ name: input.name,
406
+ description: input.description,
407
+ displayNameKey: input.displayNameKey,
408
+ fieldDefinitions: input.fieldDefinitions
409
+ }
410
+ };
411
+ const result = await fetchShopifyGraphql({
412
+ query: mutation2,
413
+ variables,
414
+ dataExtractor: (data) => {
415
+ if (!data.metaobjectDefinitionCreate) {
416
+ throw new Error(
417
+ "GraphQL response missing 'metaobjectDefinitionCreate' field"
418
+ );
419
+ }
420
+ const metaobjectDefinition = data.metaobjectDefinitionCreate.metaobjectDefinition;
421
+ if (!metaobjectDefinition) {
422
+ return {
423
+ nodes: [],
424
+ userErrors: data.metaobjectDefinitionCreate.userErrors
425
+ };
426
+ }
427
+ return {
428
+ nodes: [
429
+ {
430
+ id: metaobjectDefinition.id,
431
+ name: metaobjectDefinition.name,
432
+ type: metaobjectDefinition.type
433
+ }
434
+ ],
435
+ userErrors: data.metaobjectDefinitionCreate.userErrors
436
+ };
437
+ }
438
+ });
439
+ const definitionResult = result[0];
440
+ if (!definitionResult) {
441
+ throw new Error("Metaobject definition creation returned no result");
442
+ }
443
+ logger.debug(
444
+ `Successfully created metaobject definition ${definitionResult.id}`
445
+ );
446
+ return definitionResult;
447
+ }
448
+
449
+ // src/mutations/fulfillments/createFulfillment.ts
450
+ var mutation3 = gql`#graphql
451
+ mutation createFulfillment($fulfillment: FulfillmentInput!) {
452
+ fulfillmentCreate(fulfillment: $fulfillment) {
453
+ fulfillment {
454
+ id
455
+ status
456
+ trackingInfo {
457
+ company
458
+ number
459
+ }
460
+ }
461
+ userErrors {
462
+ field
463
+ message
464
+ }
465
+ }
466
+ }
467
+ `;
468
+ function toGid(id, type) {
469
+ if (typeof id === "string" && id.startsWith("gid://")) {
470
+ return id;
471
+ }
472
+ return `gid://shopify/${type}/${id}`;
473
+ }
474
+ async function createFulfillment(fulfillmentOrderId, fulfillmentOrderLineItems, options = {}) {
475
+ const {
476
+ trackingNumber,
477
+ carrier,
478
+ trackingUrl,
479
+ notifyCustomer = true
480
+ } = options;
481
+ const fulfillmentOrderGid = toGid(fulfillmentOrderId, "FulfillmentOrder");
482
+ logger.debug(`Creating fulfillment for order ${fulfillmentOrderGid}`);
483
+ const lineItems = fulfillmentOrderLineItems.map((item) => ({
484
+ id: toGid(item.id, "FulfillmentOrderLineItem"),
485
+ quantity: item.quantity
486
+ }));
487
+ const variables = {
488
+ fulfillment: {
489
+ lineItemsByFulfillmentOrder: [
490
+ {
491
+ fulfillmentOrderId: fulfillmentOrderGid,
492
+ ...lineItems.length > 0 ? { fulfillmentOrderLineItems: lineItems } : {}
493
+ }
494
+ ],
495
+ notifyCustomer,
496
+ ...trackingNumber ? {
497
+ trackingInfo: {
498
+ number: trackingNumber,
499
+ ...carrier ? { company: carrier } : {},
500
+ ...trackingUrl ? { url: trackingUrl } : {}
501
+ }
502
+ } : {}
503
+ }
504
+ };
505
+ const result = await fetchShopifyGraphql({
506
+ query: mutation3,
507
+ variables,
508
+ dataExtractor: (data) => {
509
+ if (!data.fulfillmentCreate) {
510
+ throw new Error("GraphQL response missing 'fulfillmentCreate' field");
511
+ }
512
+ const fulfillment = data.fulfillmentCreate.fulfillment;
513
+ if (!fulfillment) {
514
+ return {
515
+ nodes: [],
516
+ userErrors: data.fulfillmentCreate.userErrors
517
+ };
518
+ }
519
+ return {
520
+ nodes: [
521
+ {
522
+ id: fulfillment.id,
523
+ status: fulfillment.status,
524
+ trackingInfo: fulfillment.trackingInfo.map((info) => ({
525
+ company: info.company ?? null,
526
+ number: info.number ?? null
527
+ }))
528
+ }
529
+ ],
530
+ userErrors: data.fulfillmentCreate.userErrors
531
+ };
532
+ }
533
+ });
534
+ const fulfillmentResult = result[0];
535
+ if (!fulfillmentResult) {
536
+ throw new Error("Fulfillment creation returned no result");
537
+ }
538
+ logger.debug(`Successfully created fulfillment ${fulfillmentResult.id}`);
539
+ return fulfillmentResult;
540
+ }
541
+
542
+ // src/queries/fulfillments/getFulfillmentTrackingIds.queries.ts
543
+ var queryFulfillmentTrackingIds = gql`#graphql
544
+ query fulfillmentTrackingIds($id: ID!) {
545
+ fulfillment(id: $id) {
546
+ id
547
+ trackingInfo(first: 50) {
548
+ company
549
+ number
550
+ }
551
+ }
552
+ }
553
+ `;
554
+
555
+ // src/queries/fulfillments/getFulfillmentTrackingIds.ts
556
+ async function getFulfillmentTrackingIds(id) {
557
+ const gid = typeof id === "string" ? id : convertIdIntoGid(
558
+ typeof id === "number" ? BigInt(id) : id,
559
+ "Fulfillment"
560
+ );
561
+ const variables = { id: gid };
562
+ const response = await fetchShopifyGraphql({
563
+ query: queryFulfillmentTrackingIds,
564
+ variables
565
+ });
566
+ if (!response.fulfillment) {
567
+ logger.debug(`No fulfillment found with ID: ${id}`);
568
+ return void 0;
569
+ }
570
+ const trackingInfo = response.fulfillment.trackingInfo;
571
+ const trackingNumbers = trackingInfo.map((info) => info.number).filter((num) => num != null);
572
+ const trackingCompany = trackingInfo[0]?.company ?? null;
573
+ return {
574
+ trackingNumbers,
575
+ trackingCompany
576
+ };
577
+ }
578
+
579
+ // src/mutations/fulfillments/updateFulfillmentTracking.ts
580
+ var mutation4 = gql`#graphql
581
+ mutation updateFulfillmentTracking(
582
+ $fulfillmentId: ID!
583
+ $trackingNumbers: [String!]!
584
+ $company: String
585
+ $notifyCustomer: Boolean
586
+ ) {
587
+ fulfillmentTrackingInfoUpdate(
588
+ fulfillmentId: $fulfillmentId
589
+ trackingInfoInput: { numbers: $trackingNumbers, company: $company }
590
+ notifyCustomer: $notifyCustomer
591
+ ) {
592
+ fulfillment {
593
+ trackingInfo {
594
+ number
595
+ company
596
+ }
597
+ }
598
+ userErrors {
599
+ field
600
+ message
601
+ }
602
+ }
603
+ }
604
+ `;
605
+ async function updateFulfillmentTracking(fulfillmentId, trackingNumber, notifyCustomer = false) {
606
+ const fulfillmentGid = typeof fulfillmentId === "string" ? fulfillmentId : convertIdIntoGid(
607
+ typeof fulfillmentId === "number" ? BigInt(fulfillmentId) : fulfillmentId,
608
+ "Fulfillment"
609
+ );
610
+ logger.debug(`Updating tracking for fulfillment ${fulfillmentGid}`);
611
+ const existingTracking = await getFulfillmentTrackingIds(fulfillmentGid);
612
+ if (!existingTracking) {
613
+ throw new Error(`Fulfillment not found: ${fulfillmentGid}`);
614
+ }
615
+ const updatedTrackingNumbers = existingTracking.trackingNumbers.includes(
616
+ trackingNumber
617
+ ) ? existingTracking.trackingNumbers : [...existingTracking.trackingNumbers, trackingNumber];
618
+ const variables = {
619
+ fulfillmentId: fulfillmentGid,
620
+ trackingNumbers: updatedTrackingNumbers,
621
+ ...existingTracking.trackingCompany ? { company: existingTracking.trackingCompany } : {},
622
+ notifyCustomer
623
+ };
624
+ const result = await fetchShopifyGraphql({
625
+ query: mutation4,
626
+ variables,
627
+ dataExtractor: (data) => {
628
+ if (!data.fulfillmentTrackingInfoUpdate) {
629
+ throw new Error(
630
+ "GraphQL response missing 'fulfillmentTrackingInfoUpdate' field"
631
+ );
632
+ }
633
+ const fulfillment = data.fulfillmentTrackingInfoUpdate.fulfillment;
634
+ const trackingInfo = fulfillment?.trackingInfo ?? [];
635
+ const trackingNumbers = trackingInfo.map((info) => info.number).filter((num) => num != null);
636
+ const trackingCompany = trackingInfo[0]?.company ?? null;
637
+ return {
638
+ nodes: [{ trackingNumbers, trackingCompany }],
639
+ userErrors: data.fulfillmentTrackingInfoUpdate.userErrors
640
+ };
641
+ }
642
+ });
643
+ const trackingResult = result[0];
644
+ if (!trackingResult) {
645
+ throw new Error("Unexpected empty result from GraphQL mutation");
646
+ }
647
+ logger.debug(
648
+ `Successfully updated tracking for fulfillment ${fulfillmentGid}`
649
+ );
650
+ return trackingResult;
651
+ }
652
+
653
+ // src/mutations/orders/cancelOrderById.ts
654
+ var mutation5 = gql`#graphql
285
655
  mutation orderCancel($orderId: ID!) {
286
656
  orderCancel(
287
657
  orderId: $orderId
@@ -298,28 +668,417 @@ var mutation = gql`#graphql
298
668
  }
299
669
  }
300
670
  `;
301
- async function cancelOrderById(orderId) {
671
+ async function cancelOrderById(orderId) {
672
+ const orderGid = typeof orderId === "string" ? orderId : convertIdIntoGid(
673
+ typeof orderId === "number" ? BigInt(orderId) : orderId,
674
+ "Order"
675
+ );
676
+ logger.debug(`Cancelling order ${orderGid}`);
677
+ const variables = { orderId: orderGid };
678
+ await fetchShopifyGraphql({
679
+ query: mutation5,
680
+ variables,
681
+ dataExtractor: (data) => {
682
+ if (!data.orderCancel) {
683
+ throw new Error("GraphQL response missing 'orderCancel' field");
684
+ }
685
+ return {
686
+ nodes: [{ success: true }],
687
+ userErrors: data.orderCancel.orderCancelUserErrors
688
+ };
689
+ }
690
+ });
691
+ logger.debug(`Order ${orderGid} cancelled successfully`);
692
+ return true;
693
+ }
694
+
695
+ // src/mutations/refunds/createRefund.ts
696
+ var mutation6 = gql`#graphql
697
+ mutation createRefund($input: RefundInput!) {
698
+ refundCreate(input: $input) {
699
+ refund {
700
+ id
701
+ totalRefundedSet {
702
+ shopMoney {
703
+ amount
704
+ currencyCode
705
+ }
706
+ presentmentMoney {
707
+ amount
708
+ currencyCode
709
+ }
710
+ }
711
+ }
712
+ userErrors {
713
+ field
714
+ message
715
+ }
716
+ }
717
+ }
718
+ `;
719
+ function toGid2(id, type) {
720
+ if (typeof id === "string" && id.startsWith("gid://")) {
721
+ return id;
722
+ }
723
+ return `gid://shopify/${type}/${id}`;
724
+ }
725
+ async function createRefund(orderId, options = {}) {
726
+ const { currency, note, notify, refundLineItems, shipping, transactions } = options;
727
+ const orderGid = toGid2(orderId, "Order");
728
+ logger.debug(`Creating refund for order ${orderGid}`);
729
+ const variables = {
730
+ input: {
731
+ orderId: orderGid,
732
+ notify,
733
+ ...currency ? { currency } : {},
734
+ ...note ? { note } : {},
735
+ ...refundLineItems?.length ? {
736
+ refundLineItems: refundLineItems.map((item) => ({
737
+ lineItemId: toGid2(item.lineItemId, "LineItem"),
738
+ quantity: item.quantity,
739
+ ...item.restockType ? { restockType: item.restockType } : {},
740
+ ...item.locationId ? { locationId: toGid2(item.locationId, "Location") } : {}
741
+ }))
742
+ } : {},
743
+ ...shipping ? {
744
+ shipping: {
745
+ ...shipping.fullRefund !== void 0 ? { fullRefund: shipping.fullRefund } : {},
746
+ ...shipping.amount ? { amount: shipping.amount } : {}
747
+ }
748
+ } : {},
749
+ ...transactions?.length ? {
750
+ transactions: transactions.map((t) => ({
751
+ amount: t.amount,
752
+ gateway: t.gateway,
753
+ kind: "REFUND" /* Refund */,
754
+ orderId: orderGid,
755
+ ...t.parentId ? { parentId: toGid2(t.parentId, "OrderTransaction") } : {}
756
+ }))
757
+ } : {}
758
+ }
759
+ };
760
+ const result = await fetchShopifyGraphql({
761
+ query: mutation6,
762
+ variables,
763
+ dataExtractor: (data) => {
764
+ if (!data.refundCreate) {
765
+ throw new Error("GraphQL response missing 'refundCreate' field");
766
+ }
767
+ const refund = data.refundCreate.refund;
768
+ if (!refund) {
769
+ return {
770
+ nodes: [],
771
+ userErrors: data.refundCreate.userErrors
772
+ };
773
+ }
774
+ return {
775
+ nodes: [
776
+ {
777
+ id: refund.id,
778
+ totalRefunded: {
779
+ shopMoney: {
780
+ amount: refund.totalRefundedSet.shopMoney.amount,
781
+ currencyCode: refund.totalRefundedSet.shopMoney.currencyCode
782
+ },
783
+ presentmentMoney: {
784
+ amount: refund.totalRefundedSet.presentmentMoney.amount,
785
+ currencyCode: refund.totalRefundedSet.presentmentMoney.currencyCode
786
+ }
787
+ }
788
+ }
789
+ ],
790
+ userErrors: data.refundCreate.userErrors
791
+ };
792
+ }
793
+ });
794
+ const refundResult = result[0];
795
+ if (!refundResult) {
796
+ throw new Error("Refund creation returned no result");
797
+ }
798
+ logger.debug(`Successfully created refund ${refundResult.id}`);
799
+ return refundResult;
800
+ }
801
+
802
+ // src/mutations/productVariantsBulkUpdate/bulkUpdateProductVariants.ts
803
+ var mutation7 = gql`#graphql
804
+ mutation bulkUpdateProductVariants(
805
+ $productId: ID!
806
+ $variants: [ProductVariantsBulkInput!]!
807
+ ) {
808
+ productVariantsBulkUpdate(
809
+ productId: $productId
810
+ variants: $variants
811
+ ) {
812
+ productVariants {
813
+ id
814
+ sku
815
+ }
816
+ userErrors {
817
+ code
818
+ field
819
+ message
820
+ }
821
+ }
822
+ }
823
+ `;
824
+ async function bulkUpdateProductVariants(productId, variants) {
825
+ logger.debug(
826
+ `Bulk updating ${variants.length} variants for product ${productId}`
827
+ );
828
+ const variables = {
829
+ productId,
830
+ variants
831
+ };
832
+ const result = await fetchShopifyGraphql({
833
+ query: mutation7,
834
+ variables,
835
+ dataExtractor: (data) => {
836
+ if (!data.productVariantsBulkUpdate) {
837
+ throw new Error(
838
+ "GraphQL response missing 'productVariantsBulkUpdate' field"
839
+ );
840
+ }
841
+ return {
842
+ nodes: (data.productVariantsBulkUpdate.productVariants ?? []).map(
843
+ (v) => ({
844
+ id: v.id,
845
+ sku: v.sku ?? null
846
+ })
847
+ ),
848
+ userErrors: data.productVariantsBulkUpdate.userErrors
849
+ };
850
+ }
851
+ });
852
+ logger.debug(`Successfully updated ${result.length} variants`);
853
+ return result;
854
+ }
855
+
856
+ // src/mutations/metaobjects/upsertMetaobject.ts
857
+ var mutation8 = gql`#graphql
858
+ mutation upsertMetaobject(
859
+ $handle: MetaobjectHandleInput!
860
+ $metaobject: MetaobjectUpsertInput!
861
+ ) {
862
+ metaobjectUpsert(handle: $handle, metaobject: $metaobject) {
863
+ metaobject {
864
+ id
865
+ handle
866
+ displayName
867
+ fields {
868
+ key
869
+ value
870
+ }
871
+ }
872
+ userErrors {
873
+ code
874
+ field
875
+ message
876
+ }
877
+ }
878
+ }
879
+ `;
880
+ async function upsertMetaobject(input) {
881
+ const { type, handle, fields } = input;
882
+ logger.debug(`Upserting metaobject type=${type} handle=${handle}`);
883
+ const variables = {
884
+ handle: { type, handle },
885
+ metaobject: { fields }
886
+ };
887
+ const response = await fetchShopifyGraphql({
888
+ query: mutation8,
889
+ variables,
890
+ dataExtractor: (data) => {
891
+ if (!data.metaobjectUpsert) {
892
+ throw new Error("GraphQL response missing 'metaobjectUpsert' field");
893
+ }
894
+ const { metaobject, userErrors } = data.metaobjectUpsert;
895
+ return {
896
+ nodes: metaobject ? [
897
+ {
898
+ id: metaobject.id,
899
+ handle: metaobject.handle,
900
+ displayName: metaobject.displayName,
901
+ fields: metaobject.fields.map((f) => ({
902
+ key: f.key,
903
+ value: f.value ?? null
904
+ }))
905
+ }
906
+ ] : [],
907
+ userErrors
908
+ };
909
+ }
910
+ });
911
+ const result = response[0];
912
+ if (!result) {
913
+ throw new Error("No metaobject returned from upsert operation");
914
+ }
915
+ logger.debug(`Metaobject upserted successfully: ${result.id}`);
916
+ return result;
917
+ }
918
+
919
+ // src/queries/orders/calculateRefund.queries.ts
920
+ var querySuggestedRefund = gql`#graphql
921
+ query suggestedRefund(
922
+ $orderId: ID!
923
+ $refundLineItems: [RefundLineItemInput!]
924
+ $refundShipping: Boolean
925
+ $shippingAmount: Money
926
+ $suggestFullRefund: Boolean
927
+ ) {
928
+ order(id: $orderId) {
929
+ id
930
+ name
931
+ suggestedRefund(
932
+ refundLineItems: $refundLineItems
933
+ refundShipping: $refundShipping
934
+ shippingAmount: $shippingAmount
935
+ suggestFullRefund: $suggestFullRefund
936
+ ) {
937
+ amountSet {
938
+ shopMoney {
939
+ amount
940
+ currencyCode
941
+ }
942
+ }
943
+ maximumRefundableSet {
944
+ shopMoney {
945
+ amount
946
+ currencyCode
947
+ }
948
+ }
949
+ subtotalSet {
950
+ shopMoney {
951
+ amount
952
+ currencyCode
953
+ }
954
+ }
955
+ totalTaxSet {
956
+ shopMoney {
957
+ amount
958
+ currencyCode
959
+ }
960
+ }
961
+ discountedSubtotalSet {
962
+ shopMoney {
963
+ amount
964
+ currencyCode
965
+ }
966
+ }
967
+ totalCartDiscountAmountSet {
968
+ shopMoney {
969
+ amount
970
+ currencyCode
971
+ }
972
+ }
973
+ shipping {
974
+ amountSet {
975
+ shopMoney {
976
+ amount
977
+ currencyCode
978
+ }
979
+ }
980
+ maximumRefundableSet {
981
+ shopMoney {
982
+ amount
983
+ currencyCode
984
+ }
985
+ }
986
+ }
987
+ refundLineItems {
988
+ lineItem {
989
+ id
990
+ sku
991
+ title
992
+ quantity
993
+ }
994
+ quantity
995
+ priceSet {
996
+ shopMoney {
997
+ amount
998
+ currencyCode
999
+ }
1000
+ }
1001
+ subtotalSet {
1002
+ shopMoney {
1003
+ amount
1004
+ currencyCode
1005
+ }
1006
+ }
1007
+ totalTaxSet {
1008
+ shopMoney {
1009
+ amount
1010
+ currencyCode
1011
+ }
1012
+ }
1013
+ restockType
1014
+ }
1015
+ suggestedTransactions {
1016
+ gateway
1017
+ kind
1018
+ amountSet {
1019
+ shopMoney {
1020
+ amount
1021
+ currencyCode
1022
+ }
1023
+ }
1024
+ maximumRefundableSet {
1025
+ shopMoney {
1026
+ amount
1027
+ currencyCode
1028
+ }
1029
+ }
1030
+ parentTransaction {
1031
+ id
1032
+ }
1033
+ }
1034
+ }
1035
+ }
1036
+ }
1037
+ `;
1038
+
1039
+ // src/queries/orders/calculateRefund.ts
1040
+ function convertLineItemIdToGid(id) {
1041
+ if (typeof id === "string") {
1042
+ return id.startsWith("gid://") ? id : `gid://shopify/LineItem/${id}`;
1043
+ }
1044
+ return `gid://shopify/LineItem/${id}`;
1045
+ }
1046
+ function mapRestockType(restockType) {
1047
+ switch (restockType) {
1048
+ case "CANCEL":
1049
+ return "CANCEL" /* Cancel */;
1050
+ case "RETURN":
1051
+ return "RETURN" /* Return */;
1052
+ default:
1053
+ return "NO_RESTOCK" /* NoRestock */;
1054
+ }
1055
+ }
1056
+ async function calculateRefund(orderId, options = {}) {
302
1057
  const orderGid = typeof orderId === "string" ? orderId : convertIdIntoGid(
303
1058
  typeof orderId === "number" ? BigInt(orderId) : orderId,
304
1059
  "Order"
305
1060
  );
306
- logger.debug(`Cancelling order ${orderGid}`);
307
- const variables = { orderId: orderGid };
308
- await fetchShopifyGraphql({
309
- query: mutation,
310
- variables,
311
- dataExtractor: (data) => {
312
- if (!data.orderCancel) {
313
- throw new Error("GraphQL response missing 'orderCancel' field");
314
- }
315
- return {
316
- nodes: [{ success: true }],
317
- userErrors: data.orderCancel.orderCancelUserErrors
318
- };
319
- }
1061
+ const variables = {
1062
+ orderId: orderGid,
1063
+ refundLineItems: options.refundLineItems?.map((item) => ({
1064
+ lineItemId: convertLineItemIdToGid(item.lineItemId),
1065
+ quantity: item.quantity,
1066
+ restockType: mapRestockType(item.restockType),
1067
+ ...item.locationId ? { locationId: item.locationId } : {}
1068
+ })),
1069
+ refundShipping: options.refundShipping,
1070
+ shippingAmount: options.shippingAmount,
1071
+ suggestFullRefund: options.suggestFullRefund
1072
+ };
1073
+ const response = await fetchShopifyGraphql({
1074
+ query: querySuggestedRefund,
1075
+ variables
320
1076
  });
321
- logger.debug(`Order ${orderGid} cancelled successfully`);
322
- return true;
1077
+ if (!response.order?.suggestedRefund) {
1078
+ logger.debug(`No refund suggestion available for order: ${orderId}`);
1079
+ return void 0;
1080
+ }
1081
+ return response.order.suggestedRefund;
323
1082
  }
324
1083
 
325
1084
  // src/queries/orders/getOrderById.ts
@@ -549,7 +1308,7 @@ var GetLeanOrderByIdReturn = import_zod3.default.object({
549
1308
  financialStatus: import_zod3.default.string().nullable(),
550
1309
  fulfillmentStatus: import_zod3.default.string().nullable(),
551
1310
  shippingAddress: AddressSchema
552
- }).nullable();
1311
+ });
553
1312
  async function getOrderById(id, detailLevel = "lean") {
554
1313
  const bigIntId = typeof id === "number" ? BigInt(id) : id;
555
1314
  if (detailLevel === "lean") {
@@ -567,7 +1326,7 @@ async function getLeanOrderById(id) {
567
1326
  });
568
1327
  if (!response.order) {
569
1328
  logger.debug(`No order found with ID: ${id}`);
570
- return null;
1329
+ return void 0;
571
1330
  }
572
1331
  const order = response.order;
573
1332
  const leanOrder = {
@@ -613,7 +1372,7 @@ async function getFullOrderById(id) {
613
1372
  });
614
1373
  if (!response.order) {
615
1374
  logger.debug(`No order found with ID: ${id}`);
616
- return null;
1375
+ return void 0;
617
1376
  }
618
1377
  return response.order;
619
1378
  }
@@ -973,7 +1732,7 @@ var GetLeanOrderByNameReturn = import_zod5.default.object({
973
1732
  }).nullable(),
974
1733
  financialStatus: import_zod5.default.string().nullable(),
975
1734
  fulfillmentStatus: import_zod5.default.string().nullable()
976
- }).nullable();
1735
+ });
977
1736
  async function getOrderByName(orderName, detailLevel = "lean") {
978
1737
  if (detailLevel === "lean") {
979
1738
  return getLeanOrderByName(orderName);
@@ -1006,7 +1765,7 @@ async function getLeanOrderByName(orderName) {
1006
1765
  const order = extractedNodes[0];
1007
1766
  if (!order) {
1008
1767
  logger.debug(`No order found with name: ${orderName}`);
1009
- return null;
1768
+ return void 0;
1010
1769
  }
1011
1770
  const leanOrder = {
1012
1771
  id: order.id,
@@ -1052,12 +1811,12 @@ async function getFullOrderByName(orderName) {
1052
1811
  });
1053
1812
  if (extractedNodes.length === 0) {
1054
1813
  logger.debug(`No order found with name: ${orderName}`);
1055
- return null;
1814
+ return void 0;
1056
1815
  }
1057
1816
  const order = extractedNodes[0];
1058
1817
  if (!order) {
1059
1818
  logger.debug(`No order found with name: ${orderName}`);
1060
- return null;
1819
+ return void 0;
1061
1820
  }
1062
1821
  return order;
1063
1822
  }
@@ -1101,7 +1860,7 @@ async function getOrderCancellationInfoByName(orderName) {
1101
1860
  const order = firstEdge?.node;
1102
1861
  if (!order) {
1103
1862
  logger.debug(`No order found with name: ${orderName}`);
1104
- return null;
1863
+ return void 0;
1105
1864
  }
1106
1865
  return order;
1107
1866
  }
@@ -1182,6 +1941,182 @@ async function getLeanProductVariants(skus) {
1182
1941
  return await returnOutputParsed(allVariants, GetLeanProductVariantsReturn);
1183
1942
  }
1184
1943
 
1944
+ // src/queries/productVariants/getProductVariantsBySkus.ts
1945
+ var import_zod9 = __toESM(require("zod"), 1);
1946
+ var GetProductVariantsBySkusReturn = import_zod9.default.array(
1947
+ import_zod9.default.object({
1948
+ productId: import_zod9.default.string(),
1949
+ productTitle: import_zod9.default.string(),
1950
+ variantId: import_zod9.default.string(),
1951
+ variantTitle: import_zod9.default.string(),
1952
+ sku: import_zod9.default.string(),
1953
+ status: import_zod9.default.enum(["ACTIVE", "ARCHIVED", "DRAFT"])
1954
+ })
1955
+ );
1956
+ async function getProductVariantsBySkus(skus, options) {
1957
+ if (skus.length === 0) {
1958
+ return [];
1959
+ }
1960
+ const queryGql = gql`#graphql
1961
+ query productVariantsBySkus($first: Int!, $after: String, $queryFilter: String) {
1962
+ productVariants(first: $first, after: $after, query: $queryFilter) {
1963
+ edges {
1964
+ node {
1965
+ id
1966
+ title
1967
+ sku
1968
+ product {
1969
+ id
1970
+ title
1971
+ status
1972
+ }
1973
+ }
1974
+ }
1975
+ pageInfo {
1976
+ hasNextPage
1977
+ endCursor
1978
+ }
1979
+ }
1980
+ }
1981
+ `;
1982
+ const skuFilter = skus.map((sku) => `sku:${sku}`).join(" OR ");
1983
+ const statusFilter = options?.activeOnly ? "product_status:active,draft" : "";
1984
+ const queryFilter = [skuFilter, statusFilter].filter(Boolean).join(" AND ");
1985
+ const initialVariables = {
1986
+ first: 250,
1987
+ queryFilter
1988
+ };
1989
+ const extractedNodes = await fetchShopifyGraphql({
1990
+ query: queryGql,
1991
+ variables: initialVariables,
1992
+ dataExtractor: (pageData) => {
1993
+ if (!pageData.productVariants) {
1994
+ throw new Error(
1995
+ "GraphQL response for product variants is missing the 'productVariants' field."
1996
+ );
1997
+ }
1998
+ const nodes = pageData.productVariants.edges.map(
1999
+ (edge) => edge.node
2000
+ );
2001
+ return {
2002
+ nodes,
2003
+ pageInfo: pageData.productVariants.pageInfo
2004
+ };
2005
+ },
2006
+ fetchAllPages: true
2007
+ });
2008
+ const allVariants = extractedNodes.flatMap((v) => {
2009
+ if (!v.sku) {
2010
+ logger.debug(
2011
+ `Product ${v.product.title} (ID: ${v.product.id}) has a variant (ID: ${v.id}) with no SKU. Filtering out.`
2012
+ );
2013
+ return [];
2014
+ }
2015
+ return [
2016
+ {
2017
+ productId: v.product.id,
2018
+ productTitle: v.product.title,
2019
+ variantId: v.id,
2020
+ variantTitle: v.title,
2021
+ sku: v.sku,
2022
+ status: v.product.status
2023
+ }
2024
+ ];
2025
+ });
2026
+ return await returnOutputParsed(allVariants, GetProductVariantsBySkusReturn);
2027
+ }
2028
+
2029
+ // src/queries/productVariants/getAllProductVariants.ts
2030
+ var import_zod11 = __toESM(require("zod"), 1);
2031
+
2032
+ // src/queries/productVariants/getAllProductVariants.queries.ts
2033
+ var queryAllProductVariants = gql`#graphql
2034
+ query allProductVariants($first: Int!, $after: String) {
2035
+ productVariants(first: $first, after: $after) {
2036
+ edges {
2037
+ node {
2038
+ id
2039
+ legacyResourceId
2040
+ sku
2041
+ barcode
2042
+ inventoryQuantity
2043
+ price
2044
+ title
2045
+ product {
2046
+ status
2047
+ title
2048
+ description
2049
+ handle
2050
+ onlineStoreUrl
2051
+ featuredImage {
2052
+ url
2053
+ }
2054
+ }
2055
+ }
2056
+ }
2057
+ pageInfo {
2058
+ hasNextPage
2059
+ endCursor
2060
+ }
2061
+ }
2062
+ }
2063
+ `;
2064
+
2065
+ // src/queries/productVariants/getAllProductVariants.ts
2066
+ var ProductVariantSchema = import_zod11.default.object({
2067
+ status: import_zod11.default.enum(["ACTIVE", "ARCHIVED", "DRAFT"]),
2068
+ sku: import_zod11.default.string(),
2069
+ barcode: import_zod11.default.string().nullable(),
2070
+ price: import_zod11.default.string(),
2071
+ title: import_zod11.default.string(),
2072
+ url: import_zod11.default.string().nullable(),
2073
+ handle: import_zod11.default.string(),
2074
+ description: import_zod11.default.string(),
2075
+ imageUrl: import_zod11.default.string().nullable(),
2076
+ inventoryQuantity: import_zod11.default.number()
2077
+ });
2078
+ var GetAllProductVariantsReturn = import_zod11.default.array(ProductVariantSchema);
2079
+ async function getAllProductVariants() {
2080
+ const initialVariables = { first: 250 };
2081
+ const extractedNodes = await fetchShopifyGraphql({
2082
+ query: queryAllProductVariants,
2083
+ variables: initialVariables,
2084
+ dataExtractor: (pageData) => {
2085
+ if (!pageData.productVariants) {
2086
+ throw new Error(
2087
+ "GraphQL response for product variants is missing the 'productVariants' field."
2088
+ );
2089
+ }
2090
+ const nodes = pageData.productVariants.edges.map(
2091
+ (edge) => edge.node
2092
+ );
2093
+ return {
2094
+ nodes,
2095
+ pageInfo: pageData.productVariants.pageInfo
2096
+ };
2097
+ },
2098
+ fetchAllPages: true
2099
+ });
2100
+ logger.debug(`Fetched ${extractedNodes.length} product variants from Shopify`);
2101
+ const allVariants = extractedNodes.map((v) => {
2102
+ const title = v.title === "Default Title" ? v.product.title : `${v.product.title} ${v.title}`;
2103
+ const url = v.product.onlineStoreUrl ? `${v.product.onlineStoreUrl}?variant=${v.legacyResourceId}` : null;
2104
+ return {
2105
+ status: v.product.status,
2106
+ sku: v.sku ?? "",
2107
+ barcode: v.barcode ?? null,
2108
+ price: v.price,
2109
+ title,
2110
+ url,
2111
+ handle: v.product.handle,
2112
+ description: v.product.description,
2113
+ imageUrl: v.product.featuredImage?.url ?? null,
2114
+ inventoryQuantity: v.inventoryQuantity ?? 0
2115
+ };
2116
+ });
2117
+ return await returnOutputParsed(allVariants, GetAllProductVariantsReturn);
2118
+ }
2119
+
1185
2120
  // src/queries/orders/getOrderPaymentDetails.queries.ts
1186
2121
  var queryOrderPaymentDetails = gql`#graphql
1187
2122
  query orderPaymentDetailsById($id: ID!) {
@@ -1214,7 +2149,7 @@ async function getOrderPaymentDetailsById(id) {
1214
2149
  });
1215
2150
  if (!response.order) {
1216
2151
  logger.debug(`No order found with ID: ${id}`);
1217
- return null;
2152
+ return void 0;
1218
2153
  }
1219
2154
  return response.order;
1220
2155
  }
@@ -1292,7 +2227,7 @@ async function getFulfillmentById(id) {
1292
2227
  });
1293
2228
  if (!response.fulfillment) {
1294
2229
  logger.debug(`No fulfillment found with ID: ${id}`);
1295
- return null;
2230
+ return void 0;
1296
2231
  }
1297
2232
  return response.fulfillment;
1298
2233
  }
@@ -1343,43 +2278,6 @@ async function getFulfillmentOrdersByOrderId(orderId) {
1343
2278
  return response.order.fulfillmentOrders.edges.map((edge) => edge.node);
1344
2279
  }
1345
2280
 
1346
- // src/queries/fulfillments/getFulfillmentTrackingIds.queries.ts
1347
- var queryFulfillmentTrackingIds = gql`#graphql
1348
- query fulfillmentTrackingIds($id: ID!) {
1349
- fulfillment(id: $id) {
1350
- id
1351
- trackingInfo(first: 50) {
1352
- company
1353
- number
1354
- }
1355
- }
1356
- }
1357
- `;
1358
-
1359
- // src/queries/fulfillments/getFulfillmentTrackingIds.ts
1360
- async function getFulfillmentTrackingIds(id) {
1361
- const gid = typeof id === "string" ? id : convertIdIntoGid(
1362
- typeof id === "number" ? BigInt(id) : id,
1363
- "Fulfillment"
1364
- );
1365
- const variables = { id: gid };
1366
- const response = await fetchShopifyGraphql({
1367
- query: queryFulfillmentTrackingIds,
1368
- variables
1369
- });
1370
- if (!response.fulfillment) {
1371
- logger.debug(`No fulfillment found with ID: ${id}`);
1372
- return null;
1373
- }
1374
- const trackingInfo = response.fulfillment.trackingInfo;
1375
- const trackingNumbers = trackingInfo.map((info) => info.number).filter((num) => num != null);
1376
- const trackingCompany = trackingInfo[0]?.company ?? null;
1377
- return {
1378
- trackingNumbers,
1379
- trackingCompany
1380
- };
1381
- }
1382
-
1383
2281
  // src/queries/customers/getCustomersByEmail.queries.ts
1384
2282
  var queryCustomersByEmail = gql`#graphql
1385
2283
  query customersByEmail($query: String!, $first: Int!) {
@@ -1436,6 +2334,56 @@ async function getCustomersByEmail(email, limit = 10) {
1436
2334
  return customers;
1437
2335
  }
1438
2336
 
2337
+ // src/queries/customerSegments/getCustomerSegmentMembers.queries.ts
2338
+ var queryCustomerSegmentMembersWithStatistics = gql`#graphql
2339
+ query customerSegmentMembersWithStatistics($query: String!, $first: Int!, $statisticsAttributeName: String!) {
2340
+ customerSegmentMembers(query: $query, first: $first) {
2341
+ statistics {
2342
+ attributeStatistics(attributeName: $statisticsAttributeName) {
2343
+ sum
2344
+ average
2345
+ }
2346
+ }
2347
+ edges {
2348
+ node {
2349
+ id
2350
+ firstName
2351
+ lastName
2352
+ displayName
2353
+ defaultEmailAddress {
2354
+ emailAddress
2355
+ }
2356
+ }
2357
+ }
2358
+ pageInfo {
2359
+ hasNextPage
2360
+ endCursor
2361
+ }
2362
+ totalCount
2363
+ }
2364
+ }
2365
+ `;
2366
+
2367
+ // src/queries/customerSegments/getCustomerSegmentMembers.ts
2368
+ async function getCustomerSegmentMembers(query, statisticsAttributeName, limit = 250) {
2369
+ const variables = {
2370
+ query,
2371
+ first: limit,
2372
+ statisticsAttributeName
2373
+ };
2374
+ const response = await fetchShopifyGraphql({
2375
+ query: queryCustomerSegmentMembersWithStatistics,
2376
+ variables
2377
+ });
2378
+ const members = response.customerSegmentMembers.edges.map((edge) => edge.node);
2379
+ logger.debug(`Found ${members.length} customer segment members`);
2380
+ return {
2381
+ members,
2382
+ totalCount: response.customerSegmentMembers.totalCount,
2383
+ statistics: response.customerSegmentMembers.statistics
2384
+ };
2385
+ }
2386
+
1439
2387
  // src/queries/orders/getOrdersByCustomerId.queries.ts
1440
2388
  var queryOrdersByCustomerId = gql`#graphql
1441
2389
  query ordersByCustomerId($customerId: ID!, $first: Int!) {
@@ -1503,21 +2451,68 @@ function parseGid(gid) {
1503
2451
  const match = gid.match(/\d+$/);
1504
2452
  return match ? Number.parseInt(match[0], 10) : 0;
1505
2453
  }
2454
+
2455
+ // src/queries/metaobjects/getMetaobjectByHandle.queries.ts
2456
+ var queryMetaobjectByHandle = gql`#graphql
2457
+ query metaobjectByHandle($handle: MetaobjectHandleInput!) {
2458
+ metaobjectByHandle(handle: $handle) {
2459
+ id
2460
+ handle
2461
+ type
2462
+ displayName
2463
+ updatedAt
2464
+ fields {
2465
+ key
2466
+ value
2467
+ type
2468
+ }
2469
+ }
2470
+ }
2471
+ `;
2472
+
2473
+ // src/queries/metaobjects/getMetaobjectByHandle.ts
2474
+ async function getMetaobjectByHandle(handle) {
2475
+ const variables = { handle };
2476
+ const response = await fetchShopifyGraphql({
2477
+ query: queryMetaobjectByHandle,
2478
+ variables
2479
+ });
2480
+ if (!response.metaobjectByHandle) {
2481
+ logger.debug(
2482
+ `No metaobject found with type "${handle.type}" and handle "${handle.handle}"`
2483
+ );
2484
+ return void 0;
2485
+ }
2486
+ return response.metaobjectByHandle;
2487
+ }
1506
2488
  // Annotate the CommonJS export names for ESM import in node:
1507
2489
  0 && (module.exports = {
1508
2490
  ShopifyUserError,
2491
+ bulkUpdateProductVariants,
2492
+ calculateRefund,
1509
2493
  cancelOrderById,
2494
+ createFile,
2495
+ createFulfillment,
2496
+ createMetaobjectDefinition,
2497
+ createRefund,
1510
2498
  deleteCustomerById,
2499
+ deleteFilesByIds,
2500
+ getAllProductVariants,
2501
+ getCustomerSegmentMembers,
1511
2502
  getCustomersByEmail,
1512
2503
  getFulfillmentById,
1513
2504
  getFulfillmentOrdersByOrderId,
1514
2505
  getFulfillmentTrackingIds,
1515
2506
  getLeanProductVariants,
2507
+ getMetaobjectByHandle,
1516
2508
  getOrderById,
1517
2509
  getOrderByName,
1518
2510
  getOrderCancellationInfoByName,
1519
2511
  getOrderPaymentDetailsById,
1520
2512
  getOrdersByCustomerId,
1521
- parseGid
2513
+ getProductVariantsBySkus,
2514
+ parseGid,
2515
+ updateFulfillmentTracking,
2516
+ upsertMetaobject
1522
2517
  });
1523
2518
  //# sourceMappingURL=index.cjs.map