@tallyui/connector-vendure 1.0.0 → 3.0.0-next.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/LICENSE +21 -0
- package/README.md +7 -0
- package/dist/index.d.ts +100 -28
- package/dist/index.js +661 -145
- package/package.json +13 -4
- package/src/auth.ts +79 -0
- package/src/capabilities.ts +44 -0
- package/src/global-settings.ts +18 -0
- package/src/index.ts +86 -47
- package/src/reconcile/ids.ts +38 -0
- package/src/reconcile/prices.ts +58 -0
- package/src/reconcile/stock.ts +48 -0
- package/src/replication/products.ts +162 -62
- package/src/replication/variant-feed.ts +108 -0
- package/src/schemas/products.ts +19 -1
- package/src/session-probe.ts +39 -0
- package/src/store-settings.ts +81 -0
- package/src/sync/products.ts +16 -9
- package/src/traits/product.ts +123 -23
- package/src/__tests__/product-traits.test.ts +0 -248
- package/src/replication/products.test.ts +0 -204
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Paul Kilmurray and TallyUI contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# TallyUI Vendure connector
|
|
2
|
+
|
|
3
|
+
## Errors
|
|
4
|
+
|
|
5
|
+
Requests with expired or rejected credentials reject with `ConnectorUnauthorizedError` (`code: 'unauthorized'`), defined in `@tallyui/core` and re-exported by this connector. The app should sign in again.
|
|
6
|
+
|
|
7
|
+
Sign-in itself rejects with `SignInError`.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
import { ProductTraits, CollectionSync, ReplicationAdapter, TallyConnector } from '@tallyui/core';
|
|
1
|
+
import { ConnectorAuth, ProductTraits, CollectionSync, ReplicationAdapter, StockReconcileAdapter, SyncContext, StoreSettingsChoice, StoreSettings, TallyConnector } from '@tallyui/core';
|
|
2
|
+
export { ConnectorUnauthorizedError } from '@tallyui/core';
|
|
2
3
|
import { RxJsonSchema } from 'rxdb';
|
|
3
4
|
|
|
5
|
+
declare const vendureSignIn: NonNullable<ConnectorAuth['signIn']>;
|
|
6
|
+
declare const vendureAuth: ConnectorAuth;
|
|
7
|
+
|
|
4
8
|
/**
|
|
5
9
|
* RxDB schema for Vendure products.
|
|
6
10
|
*
|
|
@@ -14,56 +18,124 @@ import { RxJsonSchema } from 'rxdb';
|
|
|
14
18
|
*/
|
|
15
19
|
declare const vendureProductSchema: RxJsonSchema<any>;
|
|
16
20
|
|
|
17
|
-
|
|
18
|
-
* Vendure product trait implementations.
|
|
19
|
-
*
|
|
20
|
-
* Key differences from other connectors:
|
|
21
|
-
* - Product name is `name` (same as WooCommerce, unlike Medusa's `title`)
|
|
22
|
-
* - Price is on `variants[].priceWithTax` (integer cents, like Medusa)
|
|
23
|
-
* - Images use `featuredAsset.preview` and `assets[].preview`
|
|
24
|
-
* - Stock status is a string from the Shop API: 'IN_STOCK', 'OUT_OF_STOCK', 'LOW_STOCK'
|
|
25
|
-
* - Categories are `collections[].name` (Vendure's equivalent of categories)
|
|
26
|
-
* - No native sale price — Vendure handles sales via promotions at checkout
|
|
27
|
-
* - No native barcode field — uses custom fields if configured
|
|
28
|
-
*/
|
|
29
|
-
declare const vendureProductTraits: ProductTraits;
|
|
21
|
+
declare const vendureProductTraits: ProductTraits<any>;
|
|
30
22
|
|
|
31
|
-
|
|
32
|
-
* Vendure product sync implementation.
|
|
33
|
-
*
|
|
34
|
-
* Uses the Admin GraphQL API. Vendure uses offset-based pagination
|
|
35
|
-
* with `take` and `skip` options.
|
|
36
|
-
*/
|
|
37
|
-
declare const vendureProductSync: CollectionSync;
|
|
23
|
+
declare const vendureProductSync: CollectionSync<any>;
|
|
38
24
|
|
|
39
25
|
type VendureProductCheckpoint = {
|
|
40
26
|
skip: number;
|
|
41
27
|
updatedAt: string;
|
|
28
|
+
passMax?: string;
|
|
29
|
+
passHighWater?: string;
|
|
30
|
+
passTotal?: number;
|
|
42
31
|
};
|
|
32
|
+
/** The server's updatedAt filters miss changes because it does not run in UTC (probeUpdatedAtSkew). */
|
|
33
|
+
declare class VendureTimezoneConfigError extends Error {
|
|
34
|
+
name: string;
|
|
35
|
+
readonly code: "store_misconfigured";
|
|
36
|
+
/** Only the store owner can fix it on the server, so the pull waits the store delay (`errorKind`). */
|
|
37
|
+
readonly fixedBy: "store";
|
|
38
|
+
/**
|
|
39
|
+
* The store-side remedy, for `SyncStatus`'s detail. The message's other remedy,
|
|
40
|
+
* `updatedAtSkewMs`, is a connector option on the till, so it stays in the message only.
|
|
41
|
+
*/
|
|
42
|
+
readonly fix = "run the Vendure server with its time zone set to UTC";
|
|
43
|
+
constructor();
|
|
44
|
+
}
|
|
43
45
|
/**
|
|
44
46
|
* Replication adapter for Vendure products.
|
|
45
47
|
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
48
|
+
* Pull-only (GraphQL query with offset pagination and updatedAt filtering)
|
|
49
|
+
* for RxDB's replicateRxCollection. Catalogue data is server-owned; the
|
|
50
|
+
* POS never writes products.
|
|
49
51
|
*/
|
|
52
|
+
declare const createVendureProductReplication: (barcodeField?: string, updatedAtSkewMs?: number) => ReplicationAdapter<any, VendureProductCheckpoint>;
|
|
50
53
|
declare const vendureProductReplication: ReplicationAdapter<any, VendureProductCheckpoint>;
|
|
51
54
|
|
|
52
55
|
/**
|
|
53
|
-
*
|
|
56
|
+
* Variant feed for Vendure products (ADR-060, decision 3).
|
|
57
|
+
*
|
|
58
|
+
* A variant price or stock edit bumps `ProductVariant.updatedAt` but not
|
|
59
|
+
* `Product.updatedAt`, so the product feed never sees it. This pull adapter
|
|
60
|
+
* pages changed variants with the same pass and high-water design as
|
|
61
|
+
* `createVendureProductReplication` and re-delivers their parent products,
|
|
62
|
+
* in the same document shape, into the `products` collection. It runs as a
|
|
63
|
+
* sub-adapter of the connector's combined `replication.products` adapter
|
|
64
|
+
* (`combinePullAdapters`), not as its own replication. Parents that no longer
|
|
65
|
+
* exist are skipped; deletions are the id reconcile's job.
|
|
66
|
+
*
|
|
67
|
+
* On a fresh install `seedCheckpoint` starts the cursor at the variant high
|
|
68
|
+
* water, read before the product feed's first pass, so the catalogue downloads
|
|
69
|
+
* once. An upgrade (a stored product checkpoint, none for this feed) is not
|
|
70
|
+
* seeded: its first pass re-delivers every product that has variants, once.
|
|
71
|
+
* That is deliberate: it heals any price or stock change the product feed
|
|
72
|
+
* missed before this feed existed.
|
|
73
|
+
*
|
|
74
|
+
* `variantPageSize` (the variant page `take`) is for tests and tuning.
|
|
75
|
+
*/
|
|
76
|
+
declare const createVendureVariantFeedReplication: (barcodeField?: string, updatedAtSkewMs?: number, variantPageSize?: number) => ReplicationAdapter<any, VendureProductCheckpoint>;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Stock reconciler for Vendure products (ADR-060). Stock edits bump only the
|
|
80
|
+
* variant's updatedAt and allocations bump nothing, so replication misses them.
|
|
81
|
+
* Pages are keyed by variant id; each value is the variant's stockLevels.
|
|
82
|
+
*/
|
|
83
|
+
declare const vendureStockReconcile: StockReconcileAdapter;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Reads the active channel's currency and tax-inclusivity (ADR-049), and the
|
|
87
|
+
* default tax zone's enabled, non-customer-group rates keyed by tax category
|
|
88
|
+
* id, in integer ppm rounded once. Read-only (ADR-048). Ignores `choice`:
|
|
89
|
+
* Vendure's channel is already chosen by the `vendure-token` header sent
|
|
90
|
+
* with every request, so there is no `pricingContext` either.
|
|
91
|
+
*/
|
|
92
|
+
declare const vendureStoreSettings: (context: SyncContext, _choice?: StoreSettingsChoice) => Promise<StoreSettings>;
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* The channel-wide stock defaults an `INHERIT` variant falls back to
|
|
96
|
+
* (backlog 28). Read with `vendureGlobalStockSettings` after sign-in, like
|
|
97
|
+
* `pricesIncludeTax` from `storeSettings`.
|
|
98
|
+
*/
|
|
99
|
+
declare function vendureGlobalStockSettings(context: SyncContext): Promise<{
|
|
100
|
+
trackInventory: boolean;
|
|
101
|
+
outOfStockThreshold: number;
|
|
102
|
+
}>;
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Vendure connector for Tally UI. Build one per store session, anew on each sign-in or store change:
|
|
106
|
+
* each instance owns its reconcile feed, whose queued work must never reach another store's database (#307).
|
|
54
107
|
*
|
|
55
108
|
* Connects to Vendure backends via the Admin GraphQL API.
|
|
56
109
|
* Products are stored in RxDB using a schema that mirrors the Vendure API shape.
|
|
57
110
|
*
|
|
58
111
|
* ```ts
|
|
59
|
-
* import {
|
|
112
|
+
* import { createVendureConnector } from '@tallyui/connector-vendure';
|
|
60
113
|
* import { ConnectorProvider } from '@tallyui/core';
|
|
61
114
|
*
|
|
62
|
-
*
|
|
115
|
+
* const connector = useMemo(() => createVendureConnector({ pricesIncludeTax }), [backendUrl, pricesIncludeTax]);
|
|
116
|
+
* <ConnectorProvider connector={connector}>
|
|
63
117
|
* <App />
|
|
64
118
|
* </ConnectorProvider>
|
|
65
119
|
* ```
|
|
120
|
+
*
|
|
121
|
+
* `pricesIncludeTax` must equal the POS tax setting (`TaxContext.pricesIncludeTax`);
|
|
122
|
+
* pass `settings.pricesIncludeTax` from `storeSettings`. `globalTrackInventory`
|
|
123
|
+
* and `globalOutOfStockThreshold` are the channel's stock defaults; read them
|
|
124
|
+
* with `vendureGlobalStockSettings` after sign-in, like `pricesIncludeTax`
|
|
125
|
+
* from `storeSettings`.
|
|
126
|
+
*/
|
|
127
|
+
declare const createVendureConnector: (options?: {
|
|
128
|
+
barcodeField?: string;
|
|
129
|
+
stockLocationId?: string;
|
|
130
|
+
pricesIncludeTax?: boolean;
|
|
131
|
+
updatedAtSkewMs?: number;
|
|
132
|
+
globalTrackInventory?: boolean;
|
|
133
|
+
globalOutOfStockThreshold?: number;
|
|
134
|
+
}) => TallyConnector;
|
|
135
|
+
/**
|
|
136
|
+
* @deprecated One instance for the whole app: a store switch can leak queued reconcile work across stores.
|
|
137
|
+
* Use createVendureConnector() per store session. Removed in 4.0.
|
|
66
138
|
*/
|
|
67
139
|
declare const vendureConnector: TallyConnector;
|
|
68
140
|
|
|
69
|
-
export { vendureConnector, vendureProductReplication, vendureProductSchema, vendureProductSync, vendureProductTraits };
|
|
141
|
+
export { VendureTimezoneConfigError, createVendureConnector, createVendureProductReplication, createVendureVariantFeedReplication, vendureAuth, vendureConnector, vendureGlobalStockSettings, vendureProductReplication, vendureProductSchema, vendureProductSync, vendureProductTraits, vendureSignIn, vendureStockReconcile, vendureStoreSettings };
|