@curless/shopify-adapter 0.1.0 → 0.2.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/README.md +24 -1
- package/dist/catalog.d.ts.map +1 -1
- package/dist/catalog.js +12 -1
- package/dist/catalog.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/money.d.ts +7 -1
- package/dist/money.d.ts.map +1 -1
- package/dist/money.js +13 -4
- package/dist/money.js.map +1 -1
- package/dist/orders.d.ts +2 -1
- package/dist/orders.d.ts.map +1 -1
- package/dist/orders.js +71 -8
- package/dist/orders.js.map +1 -1
- package/dist/types.d.ts +20 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -13,13 +13,14 @@ which prices and opens the checkout.
|
|
|
13
13
|
npm install @curless/shopify-adapter
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
-
## The
|
|
16
|
+
## The three halves
|
|
17
17
|
|
|
18
18
|
```ts
|
|
19
19
|
import {
|
|
20
20
|
shopifyConfigFromEnv,
|
|
21
21
|
fetchShopifyCatalog,
|
|
22
22
|
writebackShopifyOrder,
|
|
23
|
+
refundShopifyOrder,
|
|
23
24
|
} from '@curless/shopify-adapter';
|
|
24
25
|
|
|
25
26
|
const shopify = shopifyConfigFromEnv(); // null unless SHOPIFY_* env is set
|
|
@@ -50,6 +51,23 @@ No money moves in Shopify — the order is marked **paid via an external transac
|
|
|
50
51
|
and tagged `agentbank` + `protocol:…` + the agentbank order id, so it's traceable and
|
|
51
52
|
never mistaken for a Shopify Payments sale.
|
|
52
53
|
|
|
54
|
+
**3. Refund** — when agentbank refunds the sale, stop the Shopify order reading as paid:
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
// e.g. from your `order.refunded` webhook handler
|
|
58
|
+
await refundShopifyOrder(shopify, {
|
|
59
|
+
agentbankOrderId: [`order_${paymentIntentId}`, paymentIntentId], // any tag you wrote back with
|
|
60
|
+
reason: 'guest cancelled',
|
|
61
|
+
});
|
|
62
|
+
// → { refunded: true, id } | { refunded: false, reason }
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Like the writeback, this **records** the reversal rather than processing one: Shopify
|
|
66
|
+
never held this money, so the refund is created with no `transactions` and the order
|
|
67
|
+
goes to REFUNDED without Shopify trying to return funds it never took. Full-order only
|
|
68
|
+
— agentbank refunds the whole captured amount, and inventing a partial here would let
|
|
69
|
+
you record a reversal that doesn't match the money that actually went back.
|
|
70
|
+
|
|
53
71
|
## Notes
|
|
54
72
|
|
|
55
73
|
- **Auth** is Shopify's 2026 **client-credentials** grant: a Dev Dashboard app no
|
|
@@ -69,6 +87,11 @@ never mistaken for a Shopify Payments sale.
|
|
|
69
87
|
refresh, so two writebacks fired within a second can both miss and duplicate — add
|
|
70
88
|
your own in-process guard on the order id if you fire them rapidly; the tag search
|
|
71
89
|
is the cross-restart backstop.
|
|
90
|
+
- **Refunds are idempotent and safe to miss.** `refundShopifyOrder` takes one id or a
|
|
91
|
+
list, tries them in order, and returns `{refunded:false, reason}` — never throws —
|
|
92
|
+
when nothing matches or the order is already REFUNDED. Ids that could false-match a
|
|
93
|
+
Shopify search (spaces, operators) are dropped rather than searched: refunding the
|
|
94
|
+
wrong order is worse than refunding none.
|
|
72
95
|
- **Pagination.** Products paginate to completion. A single product with more than
|
|
73
96
|
250 variants has its tail dropped **with a warning** (not silently).
|
|
74
97
|
|
package/dist/catalog.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAI7D,KAAK,YAAY,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AACtE,KAAK,YAAY,GAAG;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IAGpB,aAAa,EAAE;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACtC,QAAQ,EAAE;QAAE,QAAQ,CAAC,EAAE;YAAE,WAAW,EAAE,OAAO,CAAA;SAAE,CAAC;QAAC,KAAK,EAAE,YAAY,EAAE,CAAA;KAAE,CAAC;CAC1E,CAAC;AAUF,eAAO,MAAM,eAAe,GAC1B,UAAU,YAAY,EAAE,EACxB,cAAc,MAAM,EACpB,OAAM,CAAC,GAAG,EAAE,MAAM,KAAK,IAA4C,KAClE,WAAW,
|
|
1
|
+
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAI7D,KAAK,YAAY,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AACtE,KAAK,YAAY,GAAG;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IAGpB,aAAa,EAAE;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACtC,QAAQ,EAAE;QAAE,QAAQ,CAAC,EAAE;YAAE,WAAW,EAAE,OAAO,CAAA;SAAE,CAAC;QAAC,KAAK,EAAE,YAAY,EAAE,CAAA;KAAE,CAAC;CAC1E,CAAC;AAUF,eAAO,MAAM,eAAe,GAC1B,UAAU,YAAY,EAAE,EACxB,cAAc,MAAM,EACpB,OAAM,CAAC,GAAG,EAAE,MAAM,KAAK,IAA4C,KAClE,WAAW,EAuCb,CAAC;AAiCF,eAAO,MAAM,mBAAmB,GAC9B,QAAQ,aAAa,EACrB,YAAW,OAAO,KAAa,EAC/B,OAAM,CAAC,GAAG,EAAE,MAAM,KAAK,IAA4C,KAClE,OAAO,CAAC,WAAW,EAAE,CAkBvB,CAAC"}
|
package/dist/catalog.js
CHANGED
|
@@ -22,10 +22,21 @@ export const productsToItems = (products, currencyCode, warn = (m) => console.wa
|
|
|
22
22
|
warn(`skipping a "${p.title}" variant with no SKU`);
|
|
23
23
|
continue;
|
|
24
24
|
}
|
|
25
|
+
// A single unparseable price shouldn't take down the whole catalog load —
|
|
26
|
+
// skip and warn (toMinor rejects non-plain-decimal strings), so one bad
|
|
27
|
+
// product can't empty the merchant's catalog.
|
|
28
|
+
let priceMinor;
|
|
29
|
+
try {
|
|
30
|
+
priceMinor = toMinor(v.price, currencyCode);
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
warn(`skipping "${p.title}" (${v.sku}) — unparseable price ${JSON.stringify(v.price)}`);
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
25
36
|
items.push({
|
|
26
37
|
sku: v.sku,
|
|
27
38
|
name: p.title,
|
|
28
|
-
priceMinor
|
|
39
|
+
priceMinor,
|
|
29
40
|
currency: currencyCode,
|
|
30
41
|
description: p.description,
|
|
31
42
|
imageUrl: p.featuredImage?.url,
|
package/dist/catalog.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalog.js","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,yEAAyE;AACzE,6EAA6E;AAC7E,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAgBrC,6EAA6E;AAC7E,6EAA6E;AAC7E,kDAAkD;AAClD,MAAM,iBAAiB,GAAG,GAAG,CAAC;AAE9B,2EAA2E;AAC3E,8EAA8E;AAC9E,gDAAgD;AAChD,MAAM,CAAC,MAAM,eAAe,GAAG,CAC7B,QAAwB,EACxB,YAAoB,EACpB,OAA8B,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC,EACpD,EAAE;IACjB,MAAM,KAAK,GAAkB,EAAE,CAAC;IAChC,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,8EAA8E;QAC9E,IAAI,CAAC,CAAC,QAAQ,CAAC,QAAQ,EAAE,WAAW,EAAE,CAAC;YACrC,IAAI,CACF,IAAI,CAAC,CAAC,KAAK,mBAAmB,iBAAiB,6BAA6B,iBAAiB,aAAa,CAC3G,CAAC;QACJ,CAAC;QACD,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;YACjC,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;gBACX,IAAI,CAAC,eAAe,CAAC,CAAC,KAAK,uBAAuB,CAAC,CAAC;gBACpD,SAAS;YACX,CAAC;YACD,
|
|
1
|
+
{"version":3,"file":"catalog.js","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { shopifyConfigFromEnv, exchangeToken, shopifyGraphql } from './client.js';
|
|
2
2
|
export { fetchShopifyCatalog, productsToItems } from './catalog.js';
|
|
3
|
-
export { writebackShopifyOrder } from './orders.js';
|
|
3
|
+
export { writebackShopifyOrder, refundShopifyOrder } from './orders.js';
|
|
4
4
|
export { decimalsFor, toMinor, toMajorString } from './money.js';
|
|
5
|
-
export type { CatalogItem, ShopifyConfig, OrderWriteback, WritebackResult, } from './types.js';
|
|
5
|
+
export type { CatalogItem, ShopifyConfig, OrderWriteback, WritebackResult, OrderRefund, RefundResult, } from './types.js';
|
|
6
6
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClF,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACpE,OAAO,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACxE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AACjE,YAAY,EACV,WAAW,EACX,aAAa,EACb,cAAc,EACd,eAAe,EACf,WAAW,EACX,YAAY,GACb,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -10,8 +10,10 @@
|
|
|
10
10
|
// // …after the agent pays through agentbank:
|
|
11
11
|
// await writebackShopifyOrder(shopify, { variantId, quantity, protocol, agentbankOrderId,
|
|
12
12
|
// unitPriceMinor, currency });
|
|
13
|
+
// // …and when agentbank refunds that sale (your `order.refunded` webhook):
|
|
14
|
+
// await refundShopifyOrder(shopify, { agentbankOrderId, reason });
|
|
13
15
|
export { shopifyConfigFromEnv, exchangeToken, shopifyGraphql } from './client.js';
|
|
14
16
|
export { fetchShopifyCatalog, productsToItems } from './catalog.js';
|
|
15
|
-
export { writebackShopifyOrder } from './orders.js';
|
|
17
|
+
export { writebackShopifyOrder, refundShopifyOrder } from './orders.js';
|
|
16
18
|
export { decimalsFor, toMinor, toMajorString } from './money.js';
|
|
17
19
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,8DAA8D;AAC9D,EAAE;AACF,gFAAgF;AAChF,uCAAuC;AACvC,EAAE;AACF,iFAAiF;AACjF,uFAAuF;AACvF,4EAA4E;AAC5E,gDAAgD;AAChD,4FAA4F;AAC5F,wEAAwE;AACxE,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClF,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACpE,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,8DAA8D;AAC9D,EAAE;AACF,gFAAgF;AAChF,uCAAuC;AACvC,EAAE;AACF,iFAAiF;AACjF,uFAAuF;AACvF,4EAA4E;AAC5E,gDAAgD;AAChD,4FAA4F;AAC5F,wEAAwE;AACxE,8EAA8E;AAC9E,qEAAqE;AACrE,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClF,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACpE,OAAO,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACxE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/money.d.ts
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
/** Minor-unit exponent for an ISO currency (default 2). */
|
|
2
2
|
export declare const decimalsFor: (currency: string) => number;
|
|
3
|
-
/**
|
|
3
|
+
/**
|
|
4
|
+
* Decimal-string major amount ("2450.00") → integer minor units, for `currency`.
|
|
5
|
+
* Accepts only a plain signed decimal — a thousands separator, scientific
|
|
6
|
+
* notation, or junk is REJECTED (throws) rather than silently becoming NaN or a
|
|
7
|
+
* wrong-magnitude/wrong-sign amount. The sign is applied to the whole value so a
|
|
8
|
+
* negative fraction can't flip positive (e.g. "-0.99" → -99, not +99).
|
|
9
|
+
*/
|
|
4
10
|
export declare const toMinor: (amount: string, currency: string) => number;
|
|
5
11
|
/** Integer minor units → decimal-string major amount ("245000" → "2450.00"), for `currency`. */
|
|
6
12
|
export declare const toMajorString: (minor: number, currency: string) => string;
|
package/dist/money.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"money.d.ts","sourceRoot":"","sources":["../src/money.ts"],"names":[],"mappings":"AAmCA,2DAA2D;AAC3D,eAAO,MAAM,WAAW,GAAI,UAAU,MAAM,KAAG,MACG,CAAC;AAEnD
|
|
1
|
+
{"version":3,"file":"money.d.ts","sourceRoot":"","sources":["../src/money.ts"],"names":[],"mappings":"AAmCA,2DAA2D;AAC3D,eAAO,MAAM,WAAW,GAAI,UAAU,MAAM,KAAG,MACG,CAAC;AAEnD;;;;;;GAMG;AACH,eAAO,MAAM,OAAO,GAAI,QAAQ,MAAM,EAAE,UAAU,MAAM,KAAG,MAQ1D,CAAC;AAEF,gGAAgG;AAChG,eAAO,MAAM,aAAa,GAAI,OAAO,MAAM,EAAE,UAAU,MAAM,KAAG,MACM,CAAC"}
|
package/dist/money.js
CHANGED
|
@@ -33,13 +33,22 @@ const MINOR_UNIT_DECIMALS = {
|
|
|
33
33
|
};
|
|
34
34
|
/** Minor-unit exponent for an ISO currency (default 2). */
|
|
35
35
|
export const decimalsFor = (currency) => MINOR_UNIT_DECIMALS[currency.toUpperCase()] ?? 2;
|
|
36
|
-
/**
|
|
36
|
+
/**
|
|
37
|
+
* Decimal-string major amount ("2450.00") → integer minor units, for `currency`.
|
|
38
|
+
* Accepts only a plain signed decimal — a thousands separator, scientific
|
|
39
|
+
* notation, or junk is REJECTED (throws) rather than silently becoming NaN or a
|
|
40
|
+
* wrong-magnitude/wrong-sign amount. The sign is applied to the whole value so a
|
|
41
|
+
* negative fraction can't flip positive (e.g. "-0.99" → -99, not +99).
|
|
42
|
+
*/
|
|
37
43
|
export const toMinor = (amount, currency) => {
|
|
38
44
|
const dp = decimalsFor(currency);
|
|
39
|
-
const
|
|
40
|
-
|
|
45
|
+
const m = /^(-?)(\d+)(?:\.(\d+))?$/.exec(amount.trim());
|
|
46
|
+
if (!m)
|
|
47
|
+
throw new Error(`toMinor: not a plain decimal amount: ${JSON.stringify(amount)}`);
|
|
48
|
+
const [, sign, wholeRaw, fracRaw = ''] = m;
|
|
41
49
|
const frac = `${fracRaw}${'0'.repeat(dp)}`.slice(0, dp);
|
|
42
|
-
|
|
50
|
+
const minor = Number(wholeRaw) * 10 ** dp + (dp > 0 ? Number(frac) : 0);
|
|
51
|
+
return sign === '-' ? -minor : minor;
|
|
43
52
|
};
|
|
44
53
|
/** Integer minor units → decimal-string major amount ("245000" → "2450.00"), for `currency`. */
|
|
45
54
|
export const toMajorString = (minor, currency) => (minor / 10 ** decimalsFor(currency)).toFixed(decimalsFor(currency));
|
package/dist/money.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"money.js","sourceRoot":"","sources":["../src/money.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,iFAAiF;AACjF,gFAAgF;AAChF,8EAA8E;AAC9E,gFAAgF;AAChF,4EAA4E;AAE5E,2EAA2E;AAC3E,uCAAuC;AACvC,MAAM,mBAAmB,GAA2B;IAClD,GAAG,EAAE,CAAC;IACN,GAAG,EAAE,CAAC;IACN,GAAG,EAAE,CAAC;IACN,GAAG,EAAE,CAAC;IACN,GAAG,EAAE,CAAC;IACN,GAAG,EAAE,CAAC;IACN,GAAG,EAAE,CAAC;IACN,GAAG,EAAE,CAAC;IACN,GAAG,EAAE,CAAC;IACN,GAAG,EAAE,CAAC;IACN,GAAG,EAAE,CAAC;IACN,GAAG,EAAE,CAAC;IACN,GAAG,EAAE,CAAC;IACN,GAAG,EAAE,CAAC;IACN,GAAG,EAAE,CAAC;IACN,GAAG,EAAE,CAAC;IACN,GAAG,EAAE,CAAC;IACN,GAAG,EAAE,CAAC;IACN,GAAG,EAAE,CAAC;IACN,GAAG,EAAE,CAAC;IACN,GAAG,EAAE,CAAC;IACN,GAAG,EAAE,CAAC;IACN,GAAG,EAAE,CAAC;CACP,CAAC;AAEF,2DAA2D;AAC3D,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,QAAgB,EAAU,EAAE,CACtD,mBAAmB,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,IAAI,CAAC,CAAC;AAEnD
|
|
1
|
+
{"version":3,"file":"money.js","sourceRoot":"","sources":["../src/money.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,iFAAiF;AACjF,gFAAgF;AAChF,8EAA8E;AAC9E,gFAAgF;AAChF,4EAA4E;AAE5E,2EAA2E;AAC3E,uCAAuC;AACvC,MAAM,mBAAmB,GAA2B;IAClD,GAAG,EAAE,CAAC;IACN,GAAG,EAAE,CAAC;IACN,GAAG,EAAE,CAAC;IACN,GAAG,EAAE,CAAC;IACN,GAAG,EAAE,CAAC;IACN,GAAG,EAAE,CAAC;IACN,GAAG,EAAE,CAAC;IACN,GAAG,EAAE,CAAC;IACN,GAAG,EAAE,CAAC;IACN,GAAG,EAAE,CAAC;IACN,GAAG,EAAE,CAAC;IACN,GAAG,EAAE,CAAC;IACN,GAAG,EAAE,CAAC;IACN,GAAG,EAAE,CAAC;IACN,GAAG,EAAE,CAAC;IACN,GAAG,EAAE,CAAC;IACN,GAAG,EAAE,CAAC;IACN,GAAG,EAAE,CAAC;IACN,GAAG,EAAE,CAAC;IACN,GAAG,EAAE,CAAC;IACN,GAAG,EAAE,CAAC;IACN,GAAG,EAAE,CAAC;IACN,GAAG,EAAE,CAAC;CACP,CAAC;AAEF,2DAA2D;AAC3D,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,QAAgB,EAAU,EAAE,CACtD,mBAAmB,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,IAAI,CAAC,CAAC;AAEnD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,MAAc,EAAE,QAAgB,EAAU,EAAE;IAClE,MAAM,EAAE,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;IACjC,MAAM,CAAC,GAAG,yBAAyB,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IACxD,IAAI,CAAC,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,wCAAwC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAC1F,MAAM,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;IAC3C,MAAM,IAAI,GAAG,GAAG,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACxD,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACxE,OAAO,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC;AACvC,CAAC,CAAC;AAEF,gGAAgG;AAChG,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,KAAa,EAAE,QAAgB,EAAU,EAAE,CACvE,CAAC,KAAK,GAAG,EAAE,IAAI,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC"}
|
package/dist/orders.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
import type { OrderWriteback, ShopifyConfig, WritebackResult } from './types.js';
|
|
1
|
+
import type { OrderRefund, OrderWriteback, RefundResult, ShopifyConfig, WritebackResult } from './types.js';
|
|
2
2
|
export declare const writebackShopifyOrder: (config: ShopifyConfig, input: OrderWriteback, fetchImpl?: typeof fetch) => Promise<WritebackResult>;
|
|
3
|
+
export declare const refundShopifyOrder: (config: ShopifyConfig, input: OrderRefund, fetchImpl?: typeof fetch) => Promise<RefundResult>;
|
|
3
4
|
//# sourceMappingURL=orders.d.ts.map
|
package/dist/orders.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"orders.d.ts","sourceRoot":"","sources":["../src/orders.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"orders.d.ts","sourceRoot":"","sources":["../src/orders.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EACV,WAAW,EACX,cAAc,EACd,YAAY,EACZ,aAAa,EACb,eAAe,EAChB,MAAM,YAAY,CAAC;AAMpB,eAAO,MAAM,qBAAqB,GAChC,QAAQ,aAAa,EACrB,OAAO,cAAc,EACrB,YAAW,OAAO,KAAa,KAC9B,OAAO,CAAC,eAAe,CA6DzB,CAAC;AAeF,eAAO,MAAM,kBAAkB,GAC7B,QAAQ,aAAa,EACrB,OAAO,WAAW,EAClB,YAAW,OAAO,KAAa,KAC9B,OAAO,CAAC,YAAY,CAkEtB,CAAC"}
|
package/dist/orders.js
CHANGED
|
@@ -17,16 +17,25 @@ const FIND_BY_TAG = 'query($q:String!){ orders(first:1, query:$q){ nodes{ id nam
|
|
|
17
17
|
const ORDER_CREATE = 'mutation($o:OrderCreateOrderInput!){ orderCreate(order:$o){ order{ id name } userErrors{ field message } } }';
|
|
18
18
|
export const writebackShopifyOrder = async (config, input, fetchImpl = fetch) => {
|
|
19
19
|
const token = await exchangeToken(config, fetchImpl);
|
|
20
|
+
// Only use the order id for idempotency if it's a safe, tag-searchable token —
|
|
21
|
+
// real ids (pi_…/ord_…/UUID) always are. A value with a space or a Shopify
|
|
22
|
+
// search operator would make `tag:${id}` false-match an unrelated order (and
|
|
23
|
+
// silently drop the writeback), and Shopify normalizes odd tags so the stored
|
|
24
|
+
// tag wouldn't equal the searched one (→ a duplicate). An unsafe id degrades to
|
|
25
|
+
// no-dedupe (create anyway), never mis-dedupe.
|
|
26
|
+
const idemTag = input.agentbankOrderId && /^[A-Za-z0-9_.:-]{1,255}$/.test(input.agentbankOrderId)
|
|
27
|
+
? input.agentbankOrderId
|
|
28
|
+
: undefined;
|
|
20
29
|
// Idempotency: find an existing order tagged with this agentbank order id.
|
|
21
|
-
if (
|
|
22
|
-
const found = await shopifyGraphql(config, token, FIND_BY_TAG, { q: `tag:${
|
|
30
|
+
if (idemTag) {
|
|
31
|
+
const found = await shopifyGraphql(config, token, FIND_BY_TAG, { q: `tag:${idemTag}` }, fetchImpl);
|
|
23
32
|
const existing = found.orders.nodes[0];
|
|
24
33
|
if (existing)
|
|
25
34
|
return { created: false, reason: `already written back (${existing.name})` };
|
|
26
35
|
}
|
|
27
36
|
const tags = ['agentbank', `protocol:${input.protocol}`];
|
|
28
|
-
if (
|
|
29
|
-
tags.push(
|
|
37
|
+
if (idemTag)
|
|
38
|
+
tags.push(idemTag);
|
|
30
39
|
const note = `Paid via agentbank · protocol ${input.protocol}${input.agentbankOrderId ? ` · order ${input.agentbankOrderId}` : ''}`;
|
|
31
40
|
const lineItem = {
|
|
32
41
|
variantId: `gid://shopify/ProductVariant/${input.variantId}`,
|
|
@@ -37,11 +46,9 @@ export const writebackShopifyOrder = async (config, input, fetchImpl = fetch) =>
|
|
|
37
46
|
// variant's current price. Omitting unitPriceMinor/currency keeps the variant
|
|
38
47
|
// price (Shopify's default).
|
|
39
48
|
if (input.unitPriceMinor != null && input.currency) {
|
|
49
|
+
const currencyCode = input.currency.toUpperCase(); // Shopify's CurrencyCode enum is upper-case
|
|
40
50
|
lineItem.priceSet = {
|
|
41
|
-
shopMoney: {
|
|
42
|
-
amount: toMajorString(input.unitPriceMinor, input.currency),
|
|
43
|
-
currencyCode: input.currency,
|
|
44
|
-
},
|
|
51
|
+
shopMoney: { amount: toMajorString(input.unitPriceMinor, currencyCode), currencyCode },
|
|
45
52
|
};
|
|
46
53
|
}
|
|
47
54
|
const data = await shopifyGraphql(config, token, ORDER_CREATE, { o: { lineItems: [lineItem], financialStatus: 'PAID', note, tags } }, fetchImpl);
|
|
@@ -53,4 +60,60 @@ export const writebackShopifyOrder = async (config, input, fetchImpl = fetch) =>
|
|
|
53
60
|
return { created: false, reason: 'orderCreate returned no order' };
|
|
54
61
|
return { created: true, name: order.name, id: order.id };
|
|
55
62
|
};
|
|
63
|
+
const FIND_FOR_REFUND = 'query($q:String!){ orders(first:1, query:$q){ nodes{ id name displayFinancialStatus ' +
|
|
64
|
+
'lineItems(first:50){ nodes{ id quantity } } } } }';
|
|
65
|
+
const REFUND_CREATE = 'mutation($i:RefundInput!){ refundCreate(input:$i){ refund{ id } userErrors{ field message } } }';
|
|
66
|
+
// Mark an agentbank-settled Shopify order as refunded. See OrderRefund for why
|
|
67
|
+
// this records a refund rather than processing one.
|
|
68
|
+
//
|
|
69
|
+
// Deliberately full-order only: agentbank refunds the whole captured amount
|
|
70
|
+
// (Curless refunds nothing else), so every line goes back in full. A partial
|
|
71
|
+
// would need to say WHICH lines and how many, and inventing that here would let
|
|
72
|
+
// a caller record a refund that doesn't match the money actually returned.
|
|
73
|
+
export const refundShopifyOrder = async (config, input, fetchImpl = fetch) => {
|
|
74
|
+
// Same reasoning as the writeback's idempotency tag: an id carrying a space or
|
|
75
|
+
// a Shopify search operator would false-match an unrelated order — and
|
|
76
|
+
// refunding the WRONG order is worse than not refunding this one. Unsafe
|
|
77
|
+
// candidates are dropped rather than searched.
|
|
78
|
+
const candidates = (Array.isArray(input.agentbankOrderId) ? input.agentbankOrderId : [input.agentbankOrderId]).filter((t) => typeof t === 'string' && /^[A-Za-z0-9_.:-]{1,255}$/.test(t));
|
|
79
|
+
if (candidates.length === 0) {
|
|
80
|
+
return { refunded: false, reason: 'no safe agentbank id to search by' };
|
|
81
|
+
}
|
|
82
|
+
const token = await exchangeToken(config, fetchImpl);
|
|
83
|
+
let order;
|
|
84
|
+
for (const tag of candidates) {
|
|
85
|
+
const found = await shopifyGraphql(config, token, FIND_FOR_REFUND, { q: `tag:${tag}` }, fetchImpl);
|
|
86
|
+
order = found.orders.nodes[0];
|
|
87
|
+
if (order)
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
// No order is not an error worth retrying: this sale may predate the
|
|
91
|
+
// writeback, or the store may not be the one it was written to.
|
|
92
|
+
if (!order)
|
|
93
|
+
return { refunded: false, reason: 'no Shopify order tagged with that agentbank id' };
|
|
94
|
+
// Idempotent: a redelivered refund event finds it already refunded.
|
|
95
|
+
if (/REFUNDED/i.test(order.displayFinancialStatus)) {
|
|
96
|
+
return { refunded: false, reason: `already refunded (${order.name})` };
|
|
97
|
+
}
|
|
98
|
+
const data = await shopifyGraphql(config, token, REFUND_CREATE, {
|
|
99
|
+
i: {
|
|
100
|
+
orderId: order.id,
|
|
101
|
+
note: input.reason ? `Refunded via agentbank · ${input.reason}` : 'Refunded via agentbank',
|
|
102
|
+
// NO `transactions`. That is what makes this a record rather than a
|
|
103
|
+
// payment — see OrderRefund.
|
|
104
|
+
refundLineItems: order.lineItems.nodes.map((li) => ({
|
|
105
|
+
lineItemId: li.id,
|
|
106
|
+
quantity: li.quantity,
|
|
107
|
+
restockType: input.restock ? 'RETURN' : 'NO_RESTOCK',
|
|
108
|
+
})),
|
|
109
|
+
},
|
|
110
|
+
}, fetchImpl);
|
|
111
|
+
const errs = data.refundCreate?.userErrors ?? [];
|
|
112
|
+
if (errs.length)
|
|
113
|
+
return { refunded: false, reason: errs.map((e) => e.message).join('; ') };
|
|
114
|
+
const refund = data.refundCreate?.refund;
|
|
115
|
+
if (!refund)
|
|
116
|
+
return { refunded: false, reason: 'refundCreate returned no refund' };
|
|
117
|
+
return { refunded: true, id: refund.id };
|
|
118
|
+
};
|
|
56
119
|
//# sourceMappingURL=orders.js.map
|
package/dist/orders.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"orders.js","sourceRoot":"","sources":["../src/orders.ts"],"names":[],"mappings":"AAAA,kFAAkF;AAClF,gFAAgF;AAChF,+EAA+E;AAC/E,gFAAgF;AAChF,+DAA+D;AAC/D,EAAE;AACF,+EAA+E;AAC/E,gFAAgF;AAChF,iFAAiF;AACjF,gFAAgF;AAChF,kFAAkF;AAClF,6EAA6E;AAC7E,mCAAmC;AACnC,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"orders.js","sourceRoot":"","sources":["../src/orders.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -43,4 +43,24 @@ export type WritebackResult = {
|
|
|
43
43
|
created: false;
|
|
44
44
|
reason: string;
|
|
45
45
|
};
|
|
46
|
+
export type OrderRefund = {
|
|
47
|
+
/**
|
|
48
|
+
* The tag the writeback used. Accepts SEVERAL candidates, tried in order,
|
|
49
|
+
* because the writeback keys on `orderId ?? sessionId ?? paymentIntentId` —
|
|
50
|
+
* which of the three it landed on depends on the protocol, and a refund event
|
|
51
|
+
* doesn't know. Pass every id you hold rather than guessing one.
|
|
52
|
+
*/
|
|
53
|
+
agentbankOrderId: string | string[];
|
|
54
|
+
/** Shown on the Shopify refund. */
|
|
55
|
+
reason?: string;
|
|
56
|
+
/** Put the units back into inventory. Default false — a booking has nothing to restock. */
|
|
57
|
+
restock?: boolean;
|
|
58
|
+
};
|
|
59
|
+
export type RefundResult = {
|
|
60
|
+
refunded: true;
|
|
61
|
+
id: string;
|
|
62
|
+
} | {
|
|
63
|
+
refunded: false;
|
|
64
|
+
reason: string;
|
|
65
|
+
};
|
|
46
66
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,WAAW,GAAG;IACxB,oFAAoF;IACpF,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,uFAAuF;IACvF,UAAU,EAAE,MAAM,CAAC;IACnB,4EAA4E;IAC5E,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,sGAAsG;IACtG,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,2FAA2F;IAC3F,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4FAA4F;IAC5F,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,sCAAsC;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,6CAA6C;IAC7C,QAAQ,EAAE,MAAM,CAAC;IACjB,+EAA+E;IAC/E,YAAY,EAAE,MAAM,CAAC;IACrB,gGAAgG;IAChG,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAKF,MAAM,MAAM,cAAc,GAAG;IAC3B,0DAA0D;IAC1D,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,8FAA8F;IAC9F,QAAQ,EAAE,MAAM,CAAC;IACjB,2EAA2E;IAC3E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAO1B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,eAAe,GACvB;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAC3C;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,WAAW,GAAG;IACxB,oFAAoF;IACpF,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,uFAAuF;IACvF,UAAU,EAAE,MAAM,CAAC;IACnB,4EAA4E;IAC5E,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,sGAAsG;IACtG,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,2FAA2F;IAC3F,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4FAA4F;IAC5F,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,sCAAsC;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,6CAA6C;IAC7C,QAAQ,EAAE,MAAM,CAAC;IACjB,+EAA+E;IAC/E,YAAY,EAAE,MAAM,CAAC;IACrB,gGAAgG;IAChG,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAKF,MAAM,MAAM,cAAc,GAAG;IAC3B,0DAA0D;IAC1D,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,8FAA8F;IAC9F,QAAQ,EAAE,MAAM,CAAC;IACjB,2EAA2E;IAC3E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAO1B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,eAAe,GACvB;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAC3C;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAavC,MAAM,MAAM,WAAW,GAAG;IACxB;;;;;OAKG;IACH,gBAAgB,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACpC,mCAAmC;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2FAA2F;IAC3F,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IAAE,QAAQ,EAAE,IAAI,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,QAAQ,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@curless/shopify-adapter",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Use a Shopify store as an agentbank catalog source, and record agent-settled sales back as paid Shopify orders. Maps Shopify Admin products → a generic CatalogItem your merchant backend prices from,
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Use a Shopify store as an agentbank catalog source, and record agent-settled sales back as paid Shopify orders. Maps Shopify Admin products → a generic CatalogItem your merchant backend prices from, writes an order back after an agent pays through agentbank, and records the reversal when that sale is refunded. Zero runtime dependencies (uses the platform fetch).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "dist/index.js",
|