@useairfoil/producer-shopify 0.2.0 → 0.2.1

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.
Files changed (60) hide show
  1. package/README.md +85 -248
  2. package/dist/index.d.mts +6993 -0
  3. package/dist/index.mjs +3 -0
  4. package/dist/main.d.mts +1 -0
  5. package/dist/main.mjs +698 -0
  6. package/dist/main.mjs.map +1 -0
  7. package/dist/manifest.d.mts +32 -0
  8. package/dist/manifest.mjs +51 -0
  9. package/dist/manifest.mjs.map +1 -0
  10. package/dist/{chunk-Bp6m_JJh.js → rolldown-runtime-D7D4PA-g.mjs} +4 -4
  11. package/dist/src-Bgvuhcfk.mjs +2473 -0
  12. package/dist/src-Bgvuhcfk.mjs.map +1 -0
  13. package/package.json +19 -19
  14. package/src/{auth.ts → api/auth.ts} +15 -35
  15. package/src/api/client.ts +429 -0
  16. package/src/api/graphql.ts +221 -0
  17. package/src/api/http.ts +25 -0
  18. package/src/connector.ts +266 -163
  19. package/src/create-table.ts +5 -0
  20. package/src/demo/customers.ts +412 -0
  21. package/src/demo/index.ts +31 -0
  22. package/src/demo/setup.ts +63 -0
  23. package/src/demo/shared.ts +114 -0
  24. package/src/index.ts +35 -21
  25. package/src/main.ts +8 -8
  26. package/src/manifest.ts +4 -55
  27. package/src/resources/carts/row.ts +58 -0
  28. package/src/resources/carts/webhook.ts +98 -0
  29. package/src/resources/customers/graphql.ts +175 -0
  30. package/src/resources/customers/row.ts +112 -0
  31. package/src/resources/customers/webhook.ts +30 -0
  32. package/src/resources/orders/graphql.ts +419 -0
  33. package/src/resources/orders/row.ts +180 -0
  34. package/src/resources/orders/webhook.ts +248 -0
  35. package/src/resources/products/graphql.ts +142 -0
  36. package/src/resources/products/row.ts +92 -0
  37. package/src/resources/products/webhook.ts +130 -0
  38. package/src/resources/refunds/graphql.ts +196 -0
  39. package/src/resources/refunds/row.ts +97 -0
  40. package/src/resources/refunds/webhook.ts +123 -0
  41. package/src/resources/shared.ts +293 -0
  42. package/src/sandbox.ts +3 -3
  43. package/src/start.ts +3 -5
  44. package/src/tables.ts +15 -0
  45. package/dist/index.d.ts +0 -965
  46. package/dist/index.js +0 -4
  47. package/dist/main.d.ts +0 -1
  48. package/dist/main.js +0 -49
  49. package/dist/main.js.map +0 -1
  50. package/dist/manifest-BFfx2LkS.js +0 -91
  51. package/dist/manifest-BFfx2LkS.js.map +0 -1
  52. package/dist/manifest-CPOEExQU.d.ts +0 -34
  53. package/dist/manifest.d.ts +0 -2
  54. package/dist/manifest.js +0 -3
  55. package/dist/src-DqmiLrYS.js +0 -984
  56. package/dist/src-DqmiLrYS.js.map +0 -1
  57. package/src/api.ts +0 -636
  58. package/src/schemas.ts +0 -319
  59. package/src/throttle.ts +0 -89
  60. package/src/transient-retry.ts +0 -74
@@ -0,0 +1,196 @@
1
+ import * as Schema from "effect/Schema";
2
+
3
+ import {
4
+ GraphQLMoneyBagSchema,
5
+ MoneyBagFields,
6
+ type Nodes,
7
+ PageInfoFields,
8
+ connection,
9
+ fromGraphQL,
10
+ idRef,
11
+ normalizeAmount,
12
+ pageQuery,
13
+ } from "../shared";
14
+ import {
15
+ type Refund,
16
+ RestockTypeSchema,
17
+ TransactionKindSchema,
18
+ TransactionStatusSchema,
19
+ } from "./row";
20
+
21
+ const TransactionFields = `id kind status gateway test errorCode parentTransaction { id } createdAt processedAt amountSet { ${MoneyBagFields} }`;
22
+
23
+ const RefundLineItemFields = `id lineItem { id } quantity restockType location { id } subtotalSet { ${MoneyBagFields} } totalTaxSet { ${MoneyBagFields} }`;
24
+
25
+ const RefundShippingLineFields = `id shippingLine { id } subtotalAmountSet { ${MoneyBagFields} }`;
26
+
27
+ const OrderAdjustmentFields = `id reason amountSet { ${MoneyBagFields} } taxAmountSet { ${MoneyBagFields} }`;
28
+
29
+ export const RefundFields = `
30
+ id
31
+ legacyResourceId
32
+ note
33
+ createdAt
34
+ processedAt
35
+ duties { originalDuty { id } amountSet { ${MoneyBagFields} } }
36
+ transactions(first: 10) { nodes { ${TransactionFields} } ${PageInfoFields} }
37
+ refundLineItems(first: 50) { nodes { ${RefundLineItemFields} } ${PageInfoFields} }
38
+ refundShippingLines(first: 10) { nodes { ${RefundShippingLineFields} } ${PageInfoFields} }
39
+ orderAdjustments(first: 10) { nodes { ${OrderAdjustmentFields} } ${PageInfoFields} }
40
+ `;
41
+
42
+ const refundConnectionQuery = (name: string, selection: string) => `#graphql
43
+ query ${name}($id: ID!, $first: Int!, $after: String) {
44
+ node: refund(id: $id) {
45
+ connection: ${selection}
46
+ }
47
+ }
48
+ `;
49
+
50
+ export const RefundTransactionsQuery = refundConnectionQuery(
51
+ "AirfoilRefundTransactions",
52
+ `transactions(first: $first, after: $after) { nodes { ${TransactionFields} } ${PageInfoFields} }`,
53
+ );
54
+
55
+ export const RefundLineItemsQuery = refundConnectionQuery(
56
+ "AirfoilRefundLineItems",
57
+ `refundLineItems(first: $first, after: $after) { nodes { ${RefundLineItemFields} } ${PageInfoFields} }`,
58
+ );
59
+
60
+ export const RefundShippingLinesQuery = refundConnectionQuery(
61
+ "AirfoilRefundShippingLines",
62
+ `refundShippingLines(first: $first, after: $after) { nodes { ${RefundShippingLineFields} } ${PageInfoFields} }`,
63
+ );
64
+
65
+ export const RefundOrderAdjustmentsQuery = refundConnectionQuery(
66
+ "AirfoilRefundOrderAdjustments",
67
+ `orderAdjustments(first: $first, after: $after) { nodes { ${OrderAdjustmentFields} } ${PageInfoFields} }`,
68
+ );
69
+
70
+ export const GraphQLRefundTransactionsSchema = connection(
71
+ Schema.Struct({
72
+ id: Schema.String,
73
+ kind: TransactionKindSchema,
74
+ status: TransactionStatusSchema,
75
+ gateway: Schema.NullOr(Schema.String),
76
+ test: Schema.Boolean,
77
+ errorCode: Schema.NullOr(Schema.String),
78
+ parentTransaction: idRef,
79
+ createdAt: Schema.DateFromString,
80
+ processedAt: Schema.NullOr(Schema.DateFromString),
81
+ amountSet: GraphQLMoneyBagSchema,
82
+ }),
83
+ );
84
+
85
+ export const GraphQLRefundLineItemsSchema = connection(
86
+ Schema.Struct({
87
+ id: Schema.NullOr(Schema.String),
88
+ lineItem: Schema.Struct({ id: Schema.String }),
89
+ quantity: Schema.Int,
90
+ restockType: RestockTypeSchema,
91
+ location: idRef,
92
+ subtotalSet: GraphQLMoneyBagSchema,
93
+ totalTaxSet: GraphQLMoneyBagSchema,
94
+ }),
95
+ );
96
+
97
+ export const GraphQLRefundShippingLinesSchema = connection(
98
+ Schema.Struct({
99
+ id: Schema.String,
100
+ shippingLine: idRef,
101
+ subtotalAmountSet: GraphQLMoneyBagSchema,
102
+ }),
103
+ );
104
+
105
+ export const GraphQLOrderAdjustmentsSchema = connection(
106
+ Schema.Struct({
107
+ id: Schema.String,
108
+ reason: Schema.NullOr(Schema.String),
109
+ amountSet: GraphQLMoneyBagSchema,
110
+ taxAmountSet: GraphQLMoneyBagSchema,
111
+ }),
112
+ );
113
+
114
+ export const GraphQLRefundNodeSchema = Schema.Struct({
115
+ id: Schema.String,
116
+ legacyResourceId: Schema.String,
117
+ note: Schema.NullOr(Schema.String),
118
+ createdAt: Schema.NullOr(Schema.DateFromString),
119
+ processedAt: Schema.DateFromString,
120
+ duties: Schema.NullOr(
121
+ Schema.Array(Schema.Struct({ originalDuty: idRef, amountSet: GraphQLMoneyBagSchema })),
122
+ ),
123
+ transactions: GraphQLRefundTransactionsSchema,
124
+ refundLineItems: GraphQLRefundLineItemsSchema,
125
+ refundShippingLines: GraphQLRefundShippingLinesSchema,
126
+ orderAdjustments: GraphQLOrderAdjustmentsSchema,
127
+ });
128
+
129
+ export type GraphQLRefundNode = Schema.Schema.Type<typeof GraphQLRefundNodeSchema>;
130
+
131
+ export const fromRefundNode = (
132
+ orderId: string,
133
+ node: GraphQLRefundNode,
134
+ nested: {
135
+ readonly transactions: Nodes<typeof GraphQLRefundTransactionsSchema>;
136
+ readonly refundLineItems: Nodes<typeof GraphQLRefundLineItemsSchema>;
137
+ readonly refundShippingLines: Nodes<typeof GraphQLRefundShippingLinesSchema>;
138
+ readonly orderAdjustments: Nodes<typeof GraphQLOrderAdjustmentsSchema>;
139
+ },
140
+ ): Refund => ({
141
+ id: node.id,
142
+ legacyResourceId: node.legacyResourceId,
143
+ orderId,
144
+ note: node.note ?? "",
145
+ createdAt: node.createdAt,
146
+ processedAt: node.processedAt,
147
+ transactions: nested.transactions.map((transaction) => ({
148
+ id: transaction.id,
149
+ kind: transaction.kind,
150
+ status: transaction.status,
151
+ amount: normalizeAmount(transaction.amountSet.presentmentMoney.amount),
152
+ currencyCode: transaction.amountSet.presentmentMoney.currencyCode,
153
+ gateway: transaction.gateway,
154
+ test: transaction.test,
155
+ errorCode: transaction.errorCode,
156
+ parentTransactionId: transaction.parentTransaction?.id ?? null,
157
+ createdAt: transaction.createdAt,
158
+ processedAt: transaction.processedAt,
159
+ })),
160
+ refundLineItems: nested.refundLineItems.map((item) => ({
161
+ id: item.id,
162
+ lineItemId: item.lineItem.id,
163
+ quantity: item.quantity,
164
+ restockType: item.restockType,
165
+ locationId: item.location?.id ?? null,
166
+ subtotalSet: fromGraphQL.money(item.subtotalSet),
167
+ totalTaxSet: fromGraphQL.money(item.totalTaxSet),
168
+ })),
169
+ refundShippingLines: nested.refundShippingLines.map((line) => ({
170
+ id: line.id,
171
+ shippingLineId: line.shippingLine?.id ?? null,
172
+ subtotalAmountSet: fromGraphQL.money(line.subtotalAmountSet),
173
+ })),
174
+ orderAdjustments: nested.orderAdjustments.map((adjustment) => ({
175
+ id: adjustment.id,
176
+ reason: adjustment.reason,
177
+ amountSet: fromGraphQL.money(adjustment.amountSet),
178
+ taxAmountSet: fromGraphQL.money(adjustment.taxAmountSet),
179
+ })),
180
+ duties: (node.duties ?? []).map((duty) => ({
181
+ dutyId: duty.originalDuty?.id ?? null,
182
+ amountSet: fromGraphQL.money(duty.amountSet),
183
+ })),
184
+ });
185
+
186
+ export const OrderRefundsQuery = pageQuery(
187
+ "AirfoilOrderRefunds",
188
+ "orders",
189
+ `id refunds { ${RefundFields} }`,
190
+ );
191
+
192
+ export const GraphQLOrderRefundsDataSchema = Schema.Struct({
193
+ orders: connection(
194
+ Schema.Struct({ id: Schema.String, refunds: Schema.Array(GraphQLRefundNodeSchema) }),
195
+ ),
196
+ });
@@ -0,0 +1,97 @@
1
+ import { Iceberg } from "@useairfoil/connector-kit";
2
+ import * as Schema from "effect/Schema";
3
+
4
+ import { field, moneyBag } from "../shared";
5
+
6
+ export const TransactionKindSchema = Schema.Literals([
7
+ "SALE",
8
+ "CAPTURE",
9
+ "AUTHORIZATION",
10
+ "VOID",
11
+ "REFUND",
12
+ "CHANGE",
13
+ "EMV_AUTHORIZATION",
14
+ "SUGGESTED_REFUND",
15
+ ]);
16
+
17
+ export const TransactionStatusSchema = Schema.Literals([
18
+ "SUCCESS",
19
+ "FAILURE",
20
+ "PENDING",
21
+ "ERROR",
22
+ "AWAITING_RESPONSE",
23
+ "UNKNOWN",
24
+ ]);
25
+
26
+ export const RestockTypeSchema = Schema.Literals([
27
+ "RETURN",
28
+ "CANCEL",
29
+ "LEGACY_RESTOCK",
30
+ "NO_RESTOCK",
31
+ ]);
32
+
33
+ export const RefundSchema = Schema.Struct({
34
+ id: Schema.String.pipe(field(1, "Unique refund identifier.")),
35
+ legacyResourceId: Schema.String.pipe(field(2, "Numeric refund identifier stored as text.")),
36
+ orderId: Schema.String.pipe(field(3, "Refunded order identifier.")),
37
+ note: Schema.NullOr(Schema.String).pipe(field(4, "Refund note.")),
38
+ createdAt: Schema.NullOr(Schema.Date).pipe(field(5, "Time when the refund was created.")),
39
+ processedAt: Schema.Date.pipe(field(6, "Time when the refund was processed.")),
40
+ transactions: Schema.Array(
41
+ Schema.Struct({
42
+ id: Schema.String.pipe(field(101, "Unique transaction identifier.")),
43
+ kind: TransactionKindSchema.pipe(field(102, "Kind of transaction.")),
44
+ status: TransactionStatusSchema.pipe(field(103, "Status reported for the transaction.")),
45
+ amount: Schema.String.pipe(field(104, "Amount in the customer currency.")),
46
+ currencyCode: Schema.String.pipe(field(105, "Customer currency code.")),
47
+ gateway: Schema.NullOr(Schema.String).pipe(field(106, "Payment gateway.")),
48
+ test: Schema.Boolean.pipe(field(107, "Whether the transaction is a test.")),
49
+ errorCode: Schema.NullOr(Schema.String).pipe(field(108, "Gateway error code.")),
50
+ parentTransactionId: Schema.NullOr(Schema.String).pipe(
51
+ field(109, "Transaction this one refunds."),
52
+ ),
53
+ createdAt: Schema.Date.pipe(field(110, "Time when the transaction was created.")),
54
+ processedAt: Schema.NullOr(Schema.Date).pipe(
55
+ field(111, "Time when the transaction was processed."),
56
+ ),
57
+ }).annotate({ fieldId: 100 }),
58
+ ).pipe(field(7, "Transactions that move the refunded money.")),
59
+ refundLineItems: Schema.Array(
60
+ Schema.Struct({
61
+ id: Schema.NullOr(Schema.String).pipe(field(201, "Unique refund line item identifier.")),
62
+ lineItemId: Schema.String.pipe(field(202, "Refunded order line item identifier.")),
63
+ quantity: Schema.Int.pipe(field(203, "Quantity refunded.")),
64
+ restockType: RestockTypeSchema.pipe(field(204, "How the items were restocked.")),
65
+ locationId: Schema.NullOr(Schema.String).pipe(field(205, "Restock location identifier.")),
66
+ subtotalSet: moneyBag(210).pipe(field(206, "Refunded subtotal.")),
67
+ totalTaxSet: moneyBag(220).pipe(field(207, "Refunded tax.")),
68
+ }).annotate({ fieldId: 200 }),
69
+ ).pipe(field(8, "Refunded order line items.")),
70
+ refundShippingLines: Schema.Array(
71
+ Schema.Struct({
72
+ id: Schema.String.pipe(field(301, "Unique refund shipping line identifier.")),
73
+ shippingLineId: Schema.NullOr(Schema.String).pipe(field(302, "Refunded shipping line.")),
74
+ subtotalAmountSet: moneyBag(310).pipe(field(303, "Refunded shipping amount.")),
75
+ }).annotate({ fieldId: 300 }),
76
+ ).pipe(field(9, "Refunded shipping.")),
77
+ orderAdjustments: Schema.Array(
78
+ Schema.Struct({
79
+ id: Schema.String.pipe(field(401, "Unique order adjustment identifier.")),
80
+ reason: Schema.NullOr(Schema.String).pipe(field(402, "Reason for the adjustment.")),
81
+ amountSet: moneyBag(410).pipe(field(403, "Adjustment amount.")),
82
+ taxAmountSet: moneyBag(420).pipe(field(404, "Tax on the adjustment.")),
83
+ }).annotate({ fieldId: 400 }),
84
+ ).pipe(field(10, "Refund discrepancy adjustments.")),
85
+ duties: Schema.Array(
86
+ Schema.Struct({
87
+ dutyId: Schema.NullOr(Schema.String).pipe(field(501, "Refunded duty identifier.")),
88
+ amountSet: moneyBag(510).pipe(field(502, "Refunded duty amount.")),
89
+ }).annotate({ fieldId: 500 }),
90
+ ).pipe(field(11, "Refunded duties.")),
91
+ })
92
+ .annotate({
93
+ description: "Refunds on orders in a Shopify store.",
94
+ })
95
+ .pipe(Iceberg.identifier("id"));
96
+
97
+ export type Refund = Schema.Schema.Type<typeof RefundSchema>;
@@ -0,0 +1,123 @@
1
+ import * as Schema from "effect/Schema";
2
+
3
+ import { RestMoneyBagSchema, fromRest, gid, normalizeAmount, upper } from "../shared";
4
+ import {
5
+ type Refund,
6
+ RestockTypeSchema,
7
+ TransactionKindSchema,
8
+ TransactionStatusSchema,
9
+ } from "./row";
10
+
11
+ export const RefundWebhookPayloadSchema = Schema.Struct({
12
+ id: Schema.Number,
13
+ admin_graphql_api_id: Schema.String,
14
+ order_id: Schema.Number,
15
+ note: Schema.NullOr(Schema.String),
16
+ created_at: Schema.NullOr(Schema.DateFromString),
17
+ processed_at: Schema.DateFromString,
18
+ transactions: Schema.Array(
19
+ Schema.Struct({
20
+ admin_graphql_api_id: Schema.String,
21
+ kind: upper(TransactionKindSchema),
22
+ status: upper(TransactionStatusSchema),
23
+ amount: Schema.String,
24
+ currency: Schema.String,
25
+ gateway: Schema.NullOr(Schema.String),
26
+ test: Schema.Boolean,
27
+ error_code: Schema.NullOr(Schema.String),
28
+ parent_id: Schema.NullOr(Schema.Number),
29
+ created_at: Schema.DateFromString,
30
+ processed_at: Schema.NullOr(Schema.DateFromString),
31
+ }),
32
+ ),
33
+ refund_line_items: Schema.Array(
34
+ Schema.Struct({
35
+ id: Schema.Number,
36
+ line_item_id: Schema.Number,
37
+ quantity: Schema.Int,
38
+ restock_type: upper(RestockTypeSchema),
39
+ location_id: Schema.NullOr(Schema.Number),
40
+ subtotal_set: RestMoneyBagSchema,
41
+ total_tax_set: RestMoneyBagSchema,
42
+ }),
43
+ ),
44
+ refund_shipping_lines: Schema.Array(
45
+ Schema.Struct({
46
+ id: Schema.Number,
47
+ shipping_line_id: Schema.NullOr(Schema.Number),
48
+ subtotal_amount_set: RestMoneyBagSchema,
49
+ }),
50
+ ),
51
+ order_adjustments: Schema.Array(
52
+ Schema.Struct({
53
+ id: Schema.Number,
54
+ kind: Schema.NullOr(Schema.String),
55
+ reason: Schema.NullOr(Schema.String),
56
+ amount_set: RestMoneyBagSchema,
57
+ tax_amount_set: RestMoneyBagSchema,
58
+ }),
59
+ ),
60
+ duties: Schema.Array(
61
+ Schema.Struct({
62
+ duty_id: Schema.NullOr(Schema.Number),
63
+ amount_set: RestMoneyBagSchema,
64
+ }),
65
+ ),
66
+ });
67
+
68
+ export const RefundEventSchema = Schema.toType(RefundWebhookPayloadSchema);
69
+
70
+ export type RefundWebhookPayload = Schema.Schema.Type<typeof RefundWebhookPayloadSchema>;
71
+
72
+ export const fromRefundWebhook = (payload: RefundWebhookPayload): Refund => ({
73
+ id: payload.admin_graphql_api_id,
74
+ legacyResourceId: String(payload.id),
75
+ orderId: gid("Order", payload.order_id),
76
+ note: payload.note ?? "",
77
+ createdAt: payload.created_at,
78
+ processedAt: payload.processed_at,
79
+ // Webhooks only give transaction amounts in the customer currency.
80
+ transactions: payload.transactions.map((transaction) => ({
81
+ id: transaction.admin_graphql_api_id,
82
+ kind: transaction.kind,
83
+ status: transaction.status,
84
+ amount: normalizeAmount(transaction.amount),
85
+ currencyCode: transaction.currency,
86
+ gateway: transaction.gateway,
87
+ test: transaction.test,
88
+ errorCode: transaction.error_code?.toUpperCase() ?? null,
89
+ parentTransactionId:
90
+ transaction.parent_id === null ? null : gid("OrderTransaction", transaction.parent_id),
91
+ createdAt: transaction.created_at,
92
+ processedAt: transaction.processed_at,
93
+ })),
94
+ refundLineItems: payload.refund_line_items.map((item) => ({
95
+ id: gid("RefundLineItem", item.id),
96
+ lineItemId: gid("LineItem", item.line_item_id),
97
+ quantity: item.quantity,
98
+ restockType: item.restock_type,
99
+ locationId: item.location_id === null ? null : gid("Location", item.location_id),
100
+ subtotalSet: fromRest.money(item.subtotal_set),
101
+ totalTaxSet: fromRest.money(item.total_tax_set),
102
+ })),
103
+ refundShippingLines: payload.refund_shipping_lines.map((line) => ({
104
+ id: gid("RefundShippingLine", line.id),
105
+ shippingLineId:
106
+ line.shipping_line_id === null ? null : gid("ShippingLine", line.shipping_line_id),
107
+ subtotalAmountSet: fromRest.money(line.subtotal_amount_set),
108
+ })),
109
+ // Webhooks also list refunded shipping as an adjustment. GraphQL doesn't.
110
+ orderAdjustments: payload.order_adjustments
111
+ .filter((adjustment) => adjustment.kind !== "shipping_refund")
112
+ .map((adjustment) => ({
113
+ id: gid("OrderAdjustment", adjustment.id),
114
+ // Webhooks send text like "Refund discrepancy". GraphQL sends REFUND_DISCREPANCY.
115
+ reason: adjustment.reason?.toUpperCase().replaceAll(" ", "_") ?? null,
116
+ amountSet: fromRest.money(adjustment.amount_set),
117
+ taxAmountSet: fromRest.money(adjustment.tax_amount_set),
118
+ })),
119
+ duties: payload.duties.map((duty) => ({
120
+ dutyId: duty.duty_id === null ? null : gid("Duty", duty.duty_id),
121
+ amountSet: fromRest.money(duty.amount_set),
122
+ })),
123
+ });