@curless/shopify-adapter 0.4.0 → 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/README.md +13 -4
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +17 -2
- package/dist/client.js.map +1 -1
- package/dist/types.d.ts +5 -3
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -77,10 +77,19 @@ here would let you record a reversal that doesn't match the money that actually
|
|
|
77
77
|
|
|
78
78
|
## Notes
|
|
79
79
|
|
|
80
|
-
- **Auth
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
80
|
+
- **Auth — pick by whose store it is.**
|
|
81
|
+
- **A store you do NOT own** (a real merchant): they create a custom app in
|
|
82
|
+
their own admin and give you its Admin API token. Set `SHOPIFY_ADMIN_TOKEN`
|
|
83
|
+
+ `SHOPIFY_SHOP_DOMAIN`. **This is the only option** — the client-credentials
|
|
84
|
+
grant requires the app and shop to sit in the same Shopify organization, so
|
|
85
|
+
it cannot reach a third party's store at all.
|
|
86
|
+
- **Your own store**: Shopify's 2026 **client-credentials** grant. A Dev
|
|
87
|
+
Dashboard app no longer shows a token in the UI, so you exchange
|
|
88
|
+
`SHOPIFY_CLIENT_ID` + `SHOPIFY_CLIENT_SECRET` for a short-lived Admin token
|
|
89
|
+
programmatically.
|
|
90
|
+
|
|
91
|
+
A token, when present, wins — no exchange, one fewer call and one fewer way to
|
|
92
|
+
fail. The app needs `read_products` (catalog) and
|
|
84
93
|
`write_orders` (writeback) — required scopes go in `shopify.app.toml`, then
|
|
85
94
|
`deploy` + **reinstall**. Secrets come from the environment; never hardcode them.
|
|
86
95
|
- **Amounts are currency-aware.** Prices convert to integer minor units using the
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAKhD,eAAO,MAAM,oBAAoB,GAC/B,MAAK,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAe,KACpD,aAAa,GAAG,
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAKhD,eAAO,MAAM,oBAAoB,GAC/B,MAAK,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAe,KACpD,aAAa,GAAG,IAYlB,CAAC;AAKF,eAAO,MAAM,aAAa,GACxB,QAAQ,aAAa,EACrB,YAAW,OAAO,KAAa,KAC9B,OAAO,CAAC,MAAM,CA0BhB,CAAC;AASF,eAAO,MAAM,cAAc,GAAU,CAAC,EACpC,QAAQ,aAAa,EACrB,OAAO,MAAM,EACb,OAAO,MAAM,EACb,WAAW,OAAO,EAClB,YAAW,OAAO,KAAa,KAC9B,OAAO,CAAC,CAAC,CAgBX,CAAC"}
|
package/dist/client.js
CHANGED
|
@@ -3,16 +3,31 @@
|
|
|
3
3
|
// fall back rather than fail.
|
|
4
4
|
export const shopifyConfigFromEnv = (env = process.env) => {
|
|
5
5
|
const shopDomain = env.SHOPIFY_SHOP_DOMAIN;
|
|
6
|
+
if (!shopDomain)
|
|
7
|
+
return null;
|
|
8
|
+
const apiVersion = env.SHOPIFY_API_VERSION ?? '2025-01';
|
|
9
|
+
// A direct Admin API token first — it is the ONLY thing that works for a store
|
|
10
|
+
// you do not own, and it skips the exchange entirely.
|
|
11
|
+
const adminToken = env.SHOPIFY_ADMIN_TOKEN;
|
|
12
|
+
if (adminToken)
|
|
13
|
+
return { shopDomain, adminToken, apiVersion };
|
|
6
14
|
const clientId = env.SHOPIFY_CLIENT_ID;
|
|
7
15
|
const clientSecret = env.SHOPIFY_CLIENT_SECRET;
|
|
8
|
-
if (!
|
|
16
|
+
if (!clientId || !clientSecret)
|
|
9
17
|
return null;
|
|
10
|
-
return { shopDomain, clientId, clientSecret, apiVersion
|
|
18
|
+
return { shopDomain, clientId, clientSecret, apiVersion };
|
|
11
19
|
};
|
|
12
20
|
// Exchange client id + secret for a short-lived Admin API token
|
|
13
21
|
// (grant_type=client_credentials). Form-encoded, NOT JSON. Only works when the
|
|
14
22
|
// app and store are in the same Shopify org, which a self-installed dev app is.
|
|
15
23
|
export const exchangeToken = async (config, fetchImpl = fetch) => {
|
|
24
|
+
// Already holding a token — nothing to exchange. This is the third-party
|
|
25
|
+
// merchant path, where the client-credentials grant would fail anyway.
|
|
26
|
+
if (config.adminToken)
|
|
27
|
+
return config.adminToken;
|
|
28
|
+
if (!config.clientId || !config.clientSecret) {
|
|
29
|
+
throw new Error("Shopify auth is not configured: set SHOPIFY_ADMIN_TOKEN (a custom app in the store's own admin), or SHOPIFY_CLIENT_ID + SHOPIFY_CLIENT_SECRET for a same-org app");
|
|
30
|
+
}
|
|
16
31
|
const res = await fetchImpl(`https://${config.shopDomain}/admin/oauth/access_token`, {
|
|
17
32
|
method: 'POST',
|
|
18
33
|
headers: { 'content-type': 'application/x-www-form-urlencoded' },
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AASA,kFAAkF;AAClF,gFAAgF;AAChF,8BAA8B;AAC9B,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAClC,MAA0C,OAAO,CAAC,GAAG,EAC/B,EAAE;IACxB,MAAM,UAAU,GAAG,GAAG,CAAC,mBAAmB,CAAC;IAC3C,MAAM,QAAQ,GAAG,GAAG,CAAC,iBAAiB,CAAC;IACvC,MAAM,YAAY,GAAG,GAAG,CAAC,qBAAqB,CAAC;IAC/C,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -17,10 +17,12 @@ export type CatalogItem = {
|
|
|
17
17
|
export type ShopifyConfig = {
|
|
18
18
|
/** e.g. "your-store.myshopify.com" */
|
|
19
19
|
shopDomain: string;
|
|
20
|
-
/**
|
|
21
|
-
|
|
20
|
+
/** Admin API access token (`shpat_…`) from a custom app in the store's admin. Secret. */
|
|
21
|
+
adminToken?: string;
|
|
22
|
+
/** Dev Dashboard app client id (API key). Same-org stores only. */
|
|
23
|
+
clientId?: string;
|
|
22
24
|
/** Dev Dashboard app client secret. Secret — from env only, never hardcode. */
|
|
23
|
-
clientSecret
|
|
25
|
+
clientSecret?: string;
|
|
24
26
|
/** Admin API version, e.g. "2025-01". Pinned so an API change can't silently shift behavior. */
|
|
25
27
|
apiVersion?: string;
|
|
26
28
|
};
|
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;
|
|
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;AAcF,MAAM,MAAM,aAAa,GAAG;IAC1B,sCAAsC;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,yFAAyF;IACzF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mEAAmE;IACnE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,+EAA+E;IAC/E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,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;IAClB;;;;;;;;OAQG;IACH,KAAK,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3C,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;AAOF,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,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@curless/shopify-adapter",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
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",
|