@tallyui/connector-woocommerce 3.0.0-next.1 → 3.0.0-next.2

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
@@ -35,7 +35,8 @@ The incremental pull can miss an edit: a `modified_after` that over-excludes (in
35
35
 
36
36
  ## Errors
37
37
 
38
- - `ConnectorUnauthorizedError`, from `@tallyui/core` and re-exported here: the store rejected the token (401 or 403), or `WooMissingTokenError` (a subclass) was thrown for a missing token. `error.status` is `401` (`code: 'unauthorized'`, sign in again) or `403` (`code: 'forbidden'`, signed in but not allowed: the pull retries on the store schedule; don't sign out).
38
+ - `ConnectorUnauthorizedError`, from `@tallyui/core` and re-exported here: the store refused the request (401: the token is missing, expired or revoked; 403: signed in but not allowed), or `WooMissingTokenError` (a subclass) was thrown for a missing token. `error.status` is `401` (`code: 'unauthorized'`, sign in again) or `403` (`code: 'forbidden'`, signed in but not allowed: the pull retries on the store schedule; don't sign out).
39
+ - `WooPluginUpdateRequiredError` (`code: 'unsupported_store'`, `fixedBy: 'store'`): the store answered a `jwt_auth_*` 403, which WCPOS before 1.10.8 sends for a valid token (wcpos#1863). The store owner must update WCPOS to `minVersion` (`1.10.8`); the pull retries on the store schedule and the till stays signed in.
39
40
  - `WooDateFilterError` (`code: 'unsupported_store'`): the store returned a product outside the requested date window, so it does not honour `modified_after` (WooCommerce before 5.8, or a proxy that drops the parameter). An app should show its own words for the `code`; the message, `This store needs WooCommerce 5.8 or later to sync products.`, is a plain fallback. The diagnostics are in `productId`, `bound` (the `modified_after` sent) and `received`. Today the pull retries a failed request every 5 s (RxDB's `retryTime`), one mark request each time. Stopping on errors that cannot recover is shared replication work.
40
41
  - `WooTillUpdateRequiredError` (`code: 'till_update_required'`, `fixedBy: 'till'`): the store answered 426, normally WCPOS's protocol gate (`serverCode: 'wcpos_update_required'`), so this till must be updated; the pull pauses until `resume()`.
41
42
  - `WooMissingUuidError`: a product came back without a `uuid`, so the store is not running the WCPOS Free plugin 1.10.0 or later, or the connector is not reaching it through `wcpos/v2`.
package/dist/index.d.ts CHANGED
@@ -69,6 +69,16 @@ declare class WooDateFilterError extends Error {
69
69
  readonly minVersion = "5.8";
70
70
  constructor(productId: number | undefined, bound: string, received: string | undefined);
71
71
  }
72
+ /** A stale JWT plugin 403 on WCPOS 1.10.0–1.10.7 (wcpos/woocommerce-pos#1863; fixed by 7243675c9). */
73
+ declare class WooPluginUpdateRequiredError extends Error {
74
+ readonly storeCode: string;
75
+ name: string;
76
+ readonly code: "unsupported_store";
77
+ readonly fixedBy: "store";
78
+ readonly software = "WCPOS";
79
+ readonly minVersion = "1.10.8";
80
+ constructor(storeCode: string);
81
+ }
72
82
  /**
73
83
  * Replication adapter for WooCommerce products.
74
84
  *
@@ -124,4 +134,4 @@ declare function createWooCommerceConnector(): TallyConnector;
124
134
  */
125
135
  declare const woocommerceConnector: TallyConnector;
126
136
 
127
- export { WooDateFilterError, WooMissingTokenError, WooMissingUuidError, WooTillUpdateRequiredError, createWooCommerceConnector, wcposClientPart, wooCatalogueReconcile, wooProductReplication, wooProductSchema, wooProductSync, wooProductTraits, wooReconcileFingerprint, woocommerceConnector };
137
+ export { WooDateFilterError, WooMissingTokenError, WooMissingUuidError, WooPluginUpdateRequiredError, WooTillUpdateRequiredError, createWooCommerceConnector, wcposClientPart, wooCatalogueReconcile, wooProductReplication, wooProductSchema, wooProductSync, wooProductTraits, wooReconcileFingerprint, woocommerceConnector };
package/dist/index.js CHANGED
@@ -259,6 +259,8 @@ var MAX_STORE_MESSAGE = 200;
259
259
  async function checkResponse(response) {
260
260
  if (response.ok) return;
261
261
  if (response.status === 401 || response.status === 403) {
262
+ const body = response.status === 403 ? await response.json().catch(() => void 0) : void 0;
263
+ if (typeof body?.code === "string" && body.code.startsWith("jwt_auth_")) throw new WooPluginUpdateRequiredError(body.code);
262
264
  throw new ConnectorUnauthorizedError(`WooCommerce API error: ${response.status}`, response.status);
263
265
  }
264
266
  if (response.status === 426) {
@@ -313,6 +315,17 @@ var WooDateFilterError = class extends Error {
313
315
  /** The first WooCommerce version that applies `modified_after` (5.8). */
314
316
  minVersion = "5.8";
315
317
  };
318
+ var WooPluginUpdateRequiredError = class extends Error {
319
+ constructor(storeCode) {
320
+ super("This store needs WCPOS 1.10.8 or later: the JWT Authentication plugin blocks the till on older versions.");
321
+ this.storeCode = storeCode;
322
+ }
323
+ name = "WooPluginUpdateRequiredError";
324
+ code = "unsupported_store";
325
+ fixedBy = "store";
326
+ software = "WCPOS";
327
+ minVersion = "1.10.8";
328
+ };
316
329
  var wooProductReplication = {
317
330
  pull: {
318
331
  handler: async function pull(lastCheckpoint, batchSize, context, requests = 0) {
@@ -480,7 +493,7 @@ function createWooReconcileFeed() {
480
493
  }
481
494
 
482
495
  // package.json
483
- var version = "3.0.0-next.1";
496
+ var version = "3.0.0-next.2";
484
497
 
485
498
  // src/index.ts
486
499
  import { ConnectorUnauthorizedError as ConnectorUnauthorizedError3 } from "@tallyui/core";
@@ -562,6 +575,7 @@ export {
562
575
  WooDateFilterError,
563
576
  WooMissingTokenError,
564
577
  WooMissingUuidError,
578
+ WooPluginUpdateRequiredError,
565
579
  WooTillUpdateRequiredError,
566
580
  createWooCommerceConnector,
567
581
  wcposClientPart,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tallyui/connector-woocommerce",
3
- "version": "3.0.0-next.1",
3
+ "version": "3.0.0-next.2",
4
4
  "type": "module",
5
5
  "description": "WooCommerce connector for Tally UI",
6
6
  "main": "./dist/index.js",
@@ -26,10 +26,10 @@
26
26
  "directory": "connectors/woocommerce"
27
27
  },
28
28
  "peerDependencies": {
29
- "@tallyui/core": "^3.0.0-next.1"
29
+ "@tallyui/core": "^3.0.0-next.2"
30
30
  },
31
31
  "devDependencies": {
32
- "@tallyui/database": "3.0.0-next.1",
32
+ "@tallyui/database": "3.0.0-next.2",
33
33
  "rxdb": "17.5.0"
34
34
  },
35
35
  "scripts": {
package/src/index.ts CHANGED
@@ -119,5 +119,5 @@ export { ConnectorUnauthorizedError } from '@tallyui/core';
119
119
  export { wooProductSchema } from './schemas/products';
120
120
  export { wooProductTraits } from './traits/product';
121
121
  export { wooProductSync } from './sync/products';
122
- export { wooProductReplication, WooDateFilterError, WooMissingUuidError, WooTillUpdateRequiredError } from './replication/products';
122
+ export { wooProductReplication, WooDateFilterError, WooPluginUpdateRequiredError, WooMissingUuidError, WooTillUpdateRequiredError } from './replication/products';
123
123
  export { wooCatalogueReconcile, wooReconcileFingerprint } from './reconcile/catalogue';
@@ -30,8 +30,9 @@ async function get(path: string, context: SyncContext): Promise<any> {
30
30
  /**
31
31
  * The switch for the bulk-id fast path: true only when wcpos/v2/status lists `products_id_fast_path` in
32
32
  * `capabilities` (a missing field is false). Never a version number, and never a failed attempt.
33
- * A failed read (network, non-OK, non-JSON) is "no capability known", so the paged listing runs; only a
34
- * till-class error (401, 403, 426 through checkResponse) stops the pass, since the listing would fail the same way.
33
+ * A failed status read is "no capability known"; only a 401 or 403 would make the paged listing fail the same way.
34
+ * Only a till-class error (401 `unauthorized`, 426 `till_update_required`) or an abort stops the pass.
35
+ * A 403 `forbidden` is store-class: the catalogue reconcile skips this check and tries again at the next hourly check.
35
36
  */
36
37
  export async function wooHasIdFastPath(context: SyncContext): Promise<boolean> {
37
38
  let status: any;
@@ -69,7 +70,8 @@ export function wooCatalogueReconcile(feed: Pick<ReconcileFeed<any>, 'enqueue'>)
69
70
  yield { entries: [], cursor: from };
70
71
  if (fast) {
71
72
  // The whole catalogue in one request, so `from` is moot. A store that refuses it (a store scope answers 400)
72
- // is listed page by page in this pass; only a till-class error or an abort stops it.
73
+ // falls back to the paged listing, which fails the same way. A 403 `forbidden` is skipped until the next hourly
74
+ // check; only a till-class error or an abort stops the pass.
73
75
  let rows: any;
74
76
  let failed = false;
75
77
  try {
@@ -21,6 +21,9 @@ const MAX_STORE_MESSAGE = 200;
21
21
  export async function checkResponse(response: Response) {
22
22
  if (response.ok) return;
23
23
  if (response.status === 401 || response.status === 403) {
24
+ // Older WCPOS versions leak the JWT plugin's stale 403 despite a valid token.
25
+ const body = response.status === 403 ? await response.json().catch(() => undefined) : undefined;
26
+ if (typeof body?.code === 'string' && body.code.startsWith('jwt_auth_')) throw new WooPluginUpdateRequiredError(body.code);
24
27
  throw new ConnectorUnauthorizedError(`WooCommerce API error: ${response.status}`, response.status as 401 | 403);
25
28
  }
26
29
  if (response.status === 426) {
@@ -87,6 +90,19 @@ export class WooDateFilterError extends Error {
87
90
  }
88
91
  }
89
92
 
93
+ /** A stale JWT plugin 403 on WCPOS 1.10.0–1.10.7 (wcpos/woocommerce-pos#1863; fixed by 7243675c9). */
94
+ export class WooPluginUpdateRequiredError extends Error {
95
+ name = 'WooPluginUpdateRequiredError';
96
+ readonly code = 'unsupported_store' as const;
97
+ readonly fixedBy = 'store' as const;
98
+ readonly software = 'WCPOS';
99
+ readonly minVersion = '1.10.8';
100
+
101
+ constructor(readonly storeCode: string) {
102
+ super('This store needs WCPOS 1.10.8 or later: the JWT Authentication plugin blocks the till on older versions.');
103
+ }
104
+ }
105
+
90
106
  /**
91
107
  * Replication adapter for WooCommerce products.
92
108
  *