@pintahub/shopify-next 0.3.0 → 0.4.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.
package/README.md CHANGED
@@ -27,7 +27,7 @@ SHOPIFY_GATEWAY_URL=http://shopify-gateway.internal:6100
27
27
  ```ts
28
28
  import {ShopifyClient, SearchMenusCommand, GetMenuCommand} from '@pintahub/shopify-next'
29
29
 
30
- const client = new ShopifyClient({storeId: '6543abc...'})
30
+ const client = new ShopifyClient('6543abc...')
31
31
 
32
32
  // Query
33
33
  const {items, pageInfo} = await client.send(new SearchMenusCommand({first: 50}))
@@ -78,8 +78,7 @@ const loggingMiddleware: Middleware = (next) => async (command) => {
78
78
  }
79
79
  }
80
80
 
81
- const client = new ShopifyClient({
82
- storeId,
81
+ const client = new ShopifyClient(storeId, {
83
82
  middleware: [loggingMiddleware],
84
83
  })
85
84
  ```
@@ -87,8 +86,8 @@ const client = new ShopifyClient({
87
86
  ## Override API version
88
87
 
89
88
  ```ts
90
- const beta = new ShopifyClient({storeId, apiVersion: 'unstable'})
91
- const stable = new ShopifyClient({storeId, apiVersion: '2026-01'}) // pin an older version
89
+ const beta = new ShopifyClient(storeId, {apiVersion: 'unstable'})
90
+ const stable = new ShopifyClient(storeId, {apiVersion: '2026-01'}) // pin an older version
92
91
  ```
93
92
 
94
93
  ## API surface
@@ -130,7 +129,7 @@ Full checklist: see the "Checklist when adding a new Command" section in `CLAUDE
130
129
  Services using `@pintahub/shopify-api` should migrate as two PRs each:
131
130
 
132
131
  1. Refactor v1 → v2 signature in the service code (still using the old dependency).
133
- 2. Swap `@pintahub/shopify-api` → `@pintahub/shopify-next`, replace `new AdminAPI(...)` → `new ShopifyClient({storeId})` and `admin.x.y(...)` → `client.send(new YCommand(...))`.
132
+ 2. Swap `@pintahub/shopify-api` → `@pintahub/shopify-next`, replace `new AdminAPI(...)` → `new ShopifyClient(storeId)` and `admin.x.y(...)` → `client.send(new YCommand(...))`.
134
133
 
135
134
  **Important**: three v1 mutations were removed by Shopify in 2026-04 — there is no `*LegacyCommand` shim, services must refactor:
136
135
 
@@ -1,12 +1,19 @@
1
1
  import type { Command } from './Command';
2
+ /**
3
+ * `storeId` accepts a string or any value with `toString()` (e.g. Mongo `ObjectId`) —
4
+ * coerced internally. Services usually pass `store._id` directly.
5
+ */
6
+ export type StoreId = string | {
7
+ toString(): string;
8
+ };
2
9
  export interface ShopifyClientOptions {
3
- /** Store `_id` from MongoDB. Gateway uses it to look up `admin_access_token` + subdomain. */
4
- storeId: string;
5
10
  /** Shopify Admin API version. Defaults to `2026-04`. Pass a different value (e.g. `unstable`) for new features. */
6
11
  apiVersion?: string;
7
12
  /**
8
- * Base URL of shopify-gateway. If omitted, reads `process.env.SHOPIFY_GATEWAY_URL`.
9
- * Example: `http://shopify-gateway.internal:6100` or `http://localhost:6100`.
13
+ * Base URL of shopify-gateway. Resolution order:
14
+ * 1. `gatewayBase` option
15
+ * 2. `process.env.SHOPIFY_GATEWAY_URL`
16
+ * 3. `http://localhost:6100` (default)
10
17
  */
11
18
  gatewayBase?: string;
12
19
  /** Middleware wrapping each `send()`. Composed in order (outermost first). */
@@ -28,7 +35,7 @@ export declare class ShopifyClient {
28
35
  readonly gatewayBase: string;
29
36
  private readonly raw;
30
37
  private readonly dispatch;
31
- constructor(options: ShopifyClientOptions);
38
+ constructor(storeId: StoreId, options?: ShopifyClientOptions);
32
39
  /** Execute a Command through the gateway. */
33
40
  send<I, O>(command: Command<I, O>): Promise<O>;
34
41
  }
@@ -3,22 +3,21 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ShopifyClient = void 0;
4
4
  const admin_api_client_1 = require("@shopify/admin-api-client");
5
5
  const DEFAULT_API_VERSION = '2026-04';
6
+ const DEFAULT_GATEWAY_BASE = 'http://localhost:6100';
6
7
  class ShopifyClient {
7
8
  storeId;
8
9
  apiVersion;
9
10
  gatewayBase;
10
11
  raw;
11
12
  dispatch;
12
- constructor(options) {
13
- this.storeId = options.storeId;
13
+ constructor(storeId, options = {}) {
14
+ this.storeId = storeId ? String(storeId) : '';
14
15
  this.apiVersion = options.apiVersion ?? DEFAULT_API_VERSION;
15
- this.gatewayBase = options.gatewayBase ?? process.env.SHOPIFY_GATEWAY_URL ?? '';
16
+ this.gatewayBase =
17
+ options.gatewayBase ?? process.env.SHOPIFY_GATEWAY_URL ?? DEFAULT_GATEWAY_BASE;
16
18
  if (!this.storeId) {
17
19
  throw new Error('ShopifyClient: storeId is required');
18
20
  }
19
- if (!this.gatewayBase) {
20
- throw new Error('ShopifyClient: gatewayBase not provided and SHOPIFY_GATEWAY_URL env var not set');
21
- }
22
21
  this.raw = (0, admin_api_client_1.createAdminApiClient)({
23
22
  storeDomain: 'placeholder.myshopify.com',
24
23
  accessToken: 'placeholder',
@@ -1 +1 @@
1
- {"version":3,"file":"ShopifyClient.js","sourceRoot":"","sources":["../../src/client/ShopifyClient.ts"],"names":[],"mappings":";;;AAAA,gEAAmF;AAGnF,MAAM,mBAAmB,GAAG,SAAS,CAAA;AA6BrC,MAAa,aAAa;IACR,OAAO,CAAQ;IACf,UAAU,CAAQ;IAClB,WAAW,CAAQ;IAClB,GAAG,CAAgB;IACnB,QAAQ,CAA8C;IAEvE,YAAY,OAA6B;QACvC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAA;QAC9B,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,mBAAmB,CAAA;QAC3D,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,EAAE,CAAA;QAE/E,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAA;QACvD,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACtB,MAAM,IAAI,KAAK,CACb,iFAAiF,CAClF,CAAA;QACH,CAAC;QAED,IAAI,CAAC,GAAG,GAAG,IAAA,uCAAoB,EAAC;YAC9B,WAAW,EAAE,2BAA2B;YACxC,WAAW,EAAE,aAAa;YAC1B,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,cAAc,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAC7B,KAAK,CACH,GAAG,IAAI,CAAC,WAAW,WAAW,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,UAAU,eAAe,EAC5E,IAAmB,CACpB;SACJ,CAAC,CAAA;QAEF,MAAM,IAAI,GAAG,CAAO,OAAsB,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QACxE,IAAI,CAAC,QAAQ,GAAG,CAAC,OAAO,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,WAAW,CAEpD,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,CAAA;IACjC,CAAC;IAED,6CAA6C;IAC7C,IAAI,CAAO,OAAsB;QAC/B,OAAO,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;IAC/B,CAAC;CACF;AA1CD,sCA0CC","sourcesContent":["import {createAdminApiClient, type AdminApiClient} from '@shopify/admin-api-client'\nimport type {Command} from './Command'\n\nconst DEFAULT_API_VERSION = '2026-04'\n\nexport interface ShopifyClientOptions {\n /** Store `_id` from MongoDB. Gateway uses it to look up `admin_access_token` + subdomain. */\n storeId: string\n /** Shopify Admin API version. Defaults to `2026-04`. Pass a different value (e.g. `unstable`) for new features. */\n apiVersion?: string\n /**\n * Base URL of shopify-gateway. If omitted, reads `process.env.SHOPIFY_GATEWAY_URL`.\n * Example: `http://shopify-gateway.internal:6100` or `http://localhost:6100`.\n */\n gatewayBase?: string\n /** Middleware wrapping each `send()`. Composed in order (outermost first). */\n middleware?: Middleware[]\n}\n\n/**\n * Middleware wrapping `send()`. Same pattern as `koa` / `express`:\n * const mw: Middleware = (next) => async (command) => {\n * // before\n * const result = await next(command)\n * // after\n * return result\n * }\n */\nexport type Middleware = (\n next: <I, O>(command: Command<I, O>) => Promise<O>,\n) => <I, O>(command: Command<I, O>) => Promise<O>\n\nexport class ShopifyClient {\n public readonly storeId: string\n public readonly apiVersion: string\n public readonly gatewayBase: string\n private readonly raw: AdminApiClient\n private readonly dispatch: <I, O>(command: Command<I, O>) => Promise<O>\n\n constructor(options: ShopifyClientOptions) {\n this.storeId = options.storeId\n this.apiVersion = options.apiVersion ?? DEFAULT_API_VERSION\n this.gatewayBase = options.gatewayBase ?? process.env.SHOPIFY_GATEWAY_URL ?? ''\n\n if (!this.storeId) {\n throw new Error('ShopifyClient: storeId is required')\n }\n if (!this.gatewayBase) {\n throw new Error(\n 'ShopifyClient: gatewayBase not provided and SHOPIFY_GATEWAY_URL env var not set',\n )\n }\n\n this.raw = createAdminApiClient({\n storeDomain: 'placeholder.myshopify.com',\n accessToken: 'placeholder',\n apiVersion: this.apiVersion,\n customFetchApi: (_url, init) =>\n fetch(\n `${this.gatewayBase}/stores/${this.storeId}/${this.apiVersion}/graphql.json`,\n init as RequestInit,\n ),\n })\n\n const base = <I, O>(command: Command<I, O>) => command.execute(this.raw)\n this.dispatch = (options.middleware ?? []).reduceRight<\n <I, O>(cmd: Command<I, O>) => Promise<O>\n >((next, mw) => mw(next), base)\n }\n\n /** Execute a Command through the gateway. */\n send<I, O>(command: Command<I, O>): Promise<O> {\n return this.dispatch(command)\n }\n}\n"]}
1
+ {"version":3,"file":"ShopifyClient.js","sourceRoot":"","sources":["../../src/client/ShopifyClient.ts"],"names":[],"mappings":";;;AAAA,gEAAmF;AAGnF,MAAM,mBAAmB,GAAG,SAAS,CAAA;AACrC,MAAM,oBAAoB,GAAG,uBAAuB,CAAA;AAmCpD,MAAa,aAAa;IACR,OAAO,CAAQ;IACf,UAAU,CAAQ;IAClB,WAAW,CAAQ;IAClB,GAAG,CAAgB;IACnB,QAAQ,CAA8C;IAEvE,YAAY,OAAgB,EAAE,UAAgC,EAAE;QAC9D,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;QAC7C,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,mBAAmB,CAAA;QAC3D,IAAI,CAAC,WAAW;YACd,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,oBAAoB,CAAA;QAEhF,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAA;QACvD,CAAC;QAED,IAAI,CAAC,GAAG,GAAG,IAAA,uCAAoB,EAAC;YAC9B,WAAW,EAAE,2BAA2B;YACxC,WAAW,EAAE,aAAa;YAC1B,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,cAAc,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAC7B,KAAK,CACH,GAAG,IAAI,CAAC,WAAW,WAAW,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,UAAU,eAAe,EAC5E,IAAmB,CACpB;SACJ,CAAC,CAAA;QAEF,MAAM,IAAI,GAAG,CAAO,OAAsB,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QACxE,IAAI,CAAC,QAAQ,GAAG,CAAC,OAAO,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,WAAW,CAEpD,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,CAAA;IACjC,CAAC;IAED,6CAA6C;IAC7C,IAAI,CAAO,OAAsB;QAC/B,OAAO,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;IAC/B,CAAC;CACF;AAtCD,sCAsCC","sourcesContent":["import {createAdminApiClient, type AdminApiClient} from '@shopify/admin-api-client'\nimport type {Command} from './Command'\n\nconst DEFAULT_API_VERSION = '2026-04'\nconst DEFAULT_GATEWAY_BASE = 'http://localhost:6100'\n\n/**\n * `storeId` accepts a string or any value with `toString()` (e.g. Mongo `ObjectId`) —\n * coerced internally. Services usually pass `store._id` directly.\n */\nexport type StoreId = string | {toString(): string}\n\nexport interface ShopifyClientOptions {\n /** Shopify Admin API version. Defaults to `2026-04`. Pass a different value (e.g. `unstable`) for new features. */\n apiVersion?: string\n /**\n * Base URL of shopify-gateway. Resolution order:\n * 1. `gatewayBase` option\n * 2. `process.env.SHOPIFY_GATEWAY_URL`\n * 3. `http://localhost:6100` (default)\n */\n gatewayBase?: string\n /** Middleware wrapping each `send()`. Composed in order (outermost first). */\n middleware?: Middleware[]\n}\n\n/**\n * Middleware wrapping `send()`. Same pattern as `koa` / `express`:\n * const mw: Middleware = (next) => async (command) => {\n * // before\n * const result = await next(command)\n * // after\n * return result\n * }\n */\nexport type Middleware = (\n next: <I, O>(command: Command<I, O>) => Promise<O>,\n) => <I, O>(command: Command<I, O>) => Promise<O>\n\nexport class ShopifyClient {\n public readonly storeId: string\n public readonly apiVersion: string\n public readonly gatewayBase: string\n private readonly raw: AdminApiClient\n private readonly dispatch: <I, O>(command: Command<I, O>) => Promise<O>\n\n constructor(storeId: StoreId, options: ShopifyClientOptions = {}) {\n this.storeId = storeId ? String(storeId) : ''\n this.apiVersion = options.apiVersion ?? DEFAULT_API_VERSION\n this.gatewayBase =\n options.gatewayBase ?? process.env.SHOPIFY_GATEWAY_URL ?? DEFAULT_GATEWAY_BASE\n\n if (!this.storeId) {\n throw new Error('ShopifyClient: storeId is required')\n }\n\n this.raw = createAdminApiClient({\n storeDomain: 'placeholder.myshopify.com',\n accessToken: 'placeholder',\n apiVersion: this.apiVersion,\n customFetchApi: (_url, init) =>\n fetch(\n `${this.gatewayBase}/stores/${this.storeId}/${this.apiVersion}/graphql.json`,\n init as RequestInit,\n ),\n })\n\n const base = <I, O>(command: Command<I, O>) => command.execute(this.raw)\n this.dispatch = (options.middleware ?? []).reduceRight<\n <I, O>(cmd: Command<I, O>) => Promise<O>\n >((next, mw) => mw(next), base)\n }\n\n /** Execute a Command through the gateway. */\n send<I, O>(command: Command<I, O>): Promise<O> {\n return this.dispatch(command)\n }\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { ShopifyClient, type ShopifyClientOptions, type Middleware } from './client/ShopifyClient';
1
+ export { ShopifyClient, type ShopifyClientOptions, type StoreId, type Middleware, } from './client/ShopifyClient';
2
2
  export { Command } from './client/Command';
3
3
  export { handleErrors, assertNoUserErrors, type GraphQLError, type ResponseErrors, type UserError, } from './utils/handleErrors';
4
4
  export { getGlobalID, extractIdFromGlobalID } from './utils/globalId';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,wDAAgG;AAAxF,8GAAA,aAAa,OAAA;AACrB,4CAAwC;AAAhC,kGAAA,OAAO,OAAA;AACf,qDAM6B;AAL3B,4GAAA,YAAY,OAAA;AACZ,kHAAA,kBAAkB,OAAA;AAKpB,6CAAmE;AAA3D,uGAAA,WAAW,OAAA;AAAE,iHAAA,qBAAqB,OAAA;AAE1C,gCAAgC;AAChC,uDAAoC;AACpC,sDAAmC;AACnC,mDAAgC","sourcesContent":["export {ShopifyClient, type ShopifyClientOptions, type Middleware} from './client/ShopifyClient'\nexport {Command} from './client/Command'\nexport {\n handleErrors,\n assertNoUserErrors,\n type GraphQLError,\n type ResponseErrors,\n type UserError,\n} from './utils/handleErrors'\nexport {getGlobalID, extractIdFromGlobalID} from './utils/globalId'\n\n// Commands grouped by namespace\nexport * from './commands/customers'\nexport * from './commands/payments'\nexport * from './commands/menus'\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,wDAK+B;AAJ7B,8GAAA,aAAa,OAAA;AAKf,4CAAwC;AAAhC,kGAAA,OAAO,OAAA;AACf,qDAM6B;AAL3B,4GAAA,YAAY,OAAA;AACZ,kHAAA,kBAAkB,OAAA;AAKpB,6CAAmE;AAA3D,uGAAA,WAAW,OAAA;AAAE,iHAAA,qBAAqB,OAAA;AAE1C,gCAAgC;AAChC,uDAAoC;AACpC,sDAAmC;AACnC,mDAAgC","sourcesContent":["export {\n ShopifyClient,\n type ShopifyClientOptions,\n type StoreId,\n type Middleware,\n} from './client/ShopifyClient'\nexport {Command} from './client/Command'\nexport {\n handleErrors,\n assertNoUserErrors,\n type GraphQLError,\n type ResponseErrors,\n type UserError,\n} from './utils/handleErrors'\nexport {getGlobalID, extractIdFromGlobalID} from './utils/globalId'\n\n// Commands grouped by namespace\nexport * from './commands/customers'\nexport * from './commands/payments'\nexport * from './commands/menus'\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pintahub/shopify-next",
3
- "version": "0.3.0",
3
+ "version": "0.4.1",
4
4
  "description": "Shopify Admin GraphQL client for pintahub services via shopify-gateway",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -11,6 +11,7 @@
11
11
  "build": "tsc -p tsconfig.build.json",
12
12
  "dev": "tsc -p tsconfig.build.json --watch",
13
13
  "clean": "rm -rf dist",
14
+ "prepack": "yarn clean && yarn build",
14
15
  "codegen": "graphql-codegen",
15
16
  "typecheck": "tsc --noEmit",
16
17
  "test": "vitest run",