@misiki/gocommerce-connector 0.2.0 → 0.3.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
@@ -26,6 +26,7 @@ PUBLIC_GOCOMMERCE_API_URL=https://api.shop.example # the engine
26
26
  PUBLIC_GOCOMMERCE_PROXY_PATH=/gocommerce # see "The browser and CORS"
27
27
  # PUBLIC_GOCOMMERCE_CHANNEL=web # a sales channel, if the store has several
28
28
  # PUBLIC_GOCOMMERCE_STORE=acme # under `gocommerce platform`, on a shared API host
29
+ # PUBLIC_GOCOMMERCE_LANGUAGE=fr # ask for this language (?lang=) on every read
29
30
  ```
30
31
 
31
32
  **Leave `PUBLIC_LITEKART_API_URL` unset.** The storefront rewrites every
@@ -42,7 +43,9 @@ gocommerce serve -identity -wishlist -reviews -cms -faq -menus
42
43
 
43
44
  Each is optional. Without `-identity` there is no sign-in (guest checkout
44
45
  always works); without `-reviews` products show no stars; and so on. Add
45
- `-meilisearch` (with `MEILI_HOST` and keys) for price sorting and price filters.
46
+ `-meilisearch` (with `MEILI_HOST` and keys) for price sorting and price filters,
47
+ `-newsletter` and `-contact` for the signup box and contact form, and `-b2b` for
48
+ business buyers (see "Beyond the storefront's screens").
46
49
 
47
50
  ### The browser and CORS
48
51
 
@@ -84,7 +87,7 @@ proxy path unset and point the API URL at that origin.
84
87
  | featured / trending shelves | the collection with slug `featured` / `trending`; newest products when there is none |
85
88
  | bag | `/api/carts…`, `/api/carts/{token}/discount` |
86
89
  | delivery options | `/api/checkout/rates` |
87
- | payment methods | `/api/checkout` — cash on delivery and Razorpay (see below) |
90
+ | payment methods | `/api/checkout` — cash on delivery, Razorpay, and the first hosted-page gateway (see below) |
88
91
  | place order | `POST /api/checkout/{code}` with an `Idempotency-Key` |
89
92
  | order lookup | `/api/orders/{number}?token=` (guest), `/x/identity/me/orders` (account) |
90
93
  | sign-in, sign-up, profile, password reset | `/x/identity/*` |
@@ -93,7 +96,10 @@ proxy path unset and point the API URL at that origin.
93
96
  | reviews | `/x/reviews` |
94
97
  | content pages (`/p/…`, legal pages) | `/x/cms/pages` |
95
98
  | FAQ | `/x/faq` |
96
- | menus | `/x/navigation/menus/{header,footer}`, laid over `store.menu` |
99
+ | menus | `/x/navigation/menus/{header,footer}`, laid over `store.menu`; any menu by handle |
100
+ | product specs table | the product's category attribute answers |
101
+ | attribute filters (`?attributes.color=Red`) | `/api/products?attr=color:Red` |
102
+ | newsletter box | `/x/newsletter/subscribe` |
97
103
  | contact form, product enquiries | `/x/contact/messages` |
98
104
  | price sort and filter, type-ahead | `/x/meilisearch/search`, falling back to the engine's own search |
99
105
  | store record | the storefront's own config, with the engine's currency, menus and module switches over it |
@@ -104,6 +110,36 @@ record throws `NotSupportedError`, naming the service and the method — a silen
104
110
  success would tell a shopper their message was sent when nothing left the
105
111
  browser.
106
112
 
113
+ ## Beyond the storefront's screens
114
+
115
+ Every shopper-facing route the engine serves is reachable through this package —
116
+ CI fails when the engine gains one that is not (`scripts/route-coverage.mjs`). The
117
+ routes Svelte Commerce has no screen for are reached through services named for
118
+ what they do. These answer the engine's own shapes — numeric ids, money as
119
+ `{ amount_minor, currency }` — where the family's services answer Litekart's.
120
+
121
+ | Service | Covers |
122
+ | --- | --- |
123
+ | `b2bService` (ext/b2b) | the company, roles and credit (`me`); members and roles; invitations; a quick order by SKU (`addLines`) and a repeat order (`reorder`); checkout on account with a PO number and partial lines, or an approval request; approve, reject, withdraw; quotes requested, read, accepted, declined; the public dealer form (`submitLead`) and a dealer's leads |
124
+ | `checkoutService.checkout(code)` | any payment method the engine has switched on, answering a client secret, a redirect URL or nothing to do; `listMethods()` names them all |
125
+ | `variantService` | a product's variants, one variant, and the marketplace's offers on it |
126
+ | `newsletterService` | subscribe and unsubscribe |
127
+ | `userService` | `requestEmailVerification()`, `refreshSession()`, and `claimOrder({ number })` — files a guest order under the account, explicitly: never at sign-in, where a shared computer would file one person's orders under the next |
128
+ | `menuService` | `listMenus()` and `getMenu(handle)` beyond the header and footer |
129
+ | `wishlistService` | `setEmail()` for back-in-stock mail |
130
+
131
+ The admin API is deliberately not here. It takes an operator's token, and a
132
+ storefront package runs in every shopper's browser.
133
+
134
+ ```ts
135
+ import { b2bService } from '@misiki/gocommerce-connector'
136
+
137
+ const { role, credit } = await b2bService.me()
138
+ const { cart, rejected } = await b2bService.addLines({ lines: [{ sku: 'TEE-M', quantity: 24 }] })
139
+ const placed = await b2bService.checkout({ poNumber: 'PO-1042' })
140
+ if (placed.kind === 'approval') console.log('waiting for an approver', placed.approval.id)
141
+ ```
142
+
107
143
  ## Two things this package is careful about
108
144
 
109
145
  **Money.** The engine speaks minor units and a currency code and never a
@@ -132,14 +168,20 @@ Each of these is a real gap, listed so nobody has to find it in production.
132
168
  of a request to exactly `/api/products/<slug>`; the engine's slug route is
133
169
  `/api/products/slug/<slug>`, and `/api/products/<slug>` answers 400 for a
134
170
  non-numeric id.
135
- - **Payment.** The storefront drives a fixed list of gateway flows. Of the
136
- engine's, cash on delivery and Razorpay's modal match. GoCommerce's Stripe is a
137
- Payment Element (a client secret), not the hosted page the storefront
138
- redirects to, and the engine's redirect gateways (Adyen, Paddle, Lemon
139
- Squeezy, Creem, Hyperswitch, RevenueCat) have no matching flow. They are left
140
- out of the payment list — each reported once in the console — rather than
141
- shown as a button that fails at the last step. Payment is confirmed by the
142
- gateway's webhook to the engine; the order shows `paymentStatus` once it lands.
171
+ - **Payment.** The storefront drives a fixed list of gateway flows and passes
172
+ none of them the gateway the shopper chose. Cash on delivery and Razorpay's
173
+ modal match engine gateways directly. The storefront's redirect flow (which it
174
+ reaches by the code `PAYPAL`) carries the store's first hosted-page gateway —
175
+ Adyen, Paddle, Lemon Squeezy, Creem, Hyperswitch or RevenueCat — under that
176
+ gateway's own name and a neutral card icon; a second one cannot be told apart
177
+ from the first and is not offered. GoCommerce's Stripe is a Payment Element (a
178
+ client secret), which this storefront does not mount. Every method left off is
179
+ reported once in the console, and every one is reachable through
180
+ `checkoutService.checkout(code)` for a storefront that drives its own payment
181
+ UI. Payment is confirmed by the gateway's webhook to the engine; the order
182
+ shows `paymentStatus` once it lands.
183
+ - **Attribute filters inside a category.** The engine filters by attribute on
184
+ the whole-shop listing only; on a category page they are not applied.
143
185
  - **Tax in the bag.** The engine's cart carries no tax or total; tax is computed
144
186
  when the order is placed. The bag shows subtotal − discount + delivery, and the
145
187
  order shows the real figures.
@@ -166,17 +208,22 @@ npm run typecheck
166
208
  npm test # builds, then runs both suites
167
209
  ```
168
210
 
169
- `test/unit.test.mjs` covers the translation with no engine. `test/live.test.mjs`
170
- runs the connector against a real one, seeding what it needs through the admin
171
- API under names unique to the run:
211
+ `test/unit.test.mjs` covers the translation with no engine. The live suites,
212
+ `test/live.test.mjs` and `test/live-more.test.mjs`, run the connector against a
213
+ real one, seeding what they need through the admin API under names unique to
214
+ the run:
172
215
 
173
216
  ```bash
174
- gocommerce serve -admin-token dev-token -identity -wishlist -reviews -cms -faq -menus
175
- GOCOMMERCE_URL=http://127.0.0.1:8080 GOCOMMERCE_ADMIN_TOKEN=dev-token npm test
217
+ gocommerce serve -admin-token dev-token -identity -wishlist -reviews -cms -faq -menus -newsletter -contact -b2b
218
+ GOCOMMERCE_URL=http://127.0.0.1:8080 GOCOMMERCE_ADMIN_TOKEN=dev-token \
219
+ GOCOMMERCE_TEST_DB=postgres://…/the-stores-database npm test
176
220
  ```
177
221
 
178
- It skips, loudly, when there is no engine. CI runs it against GoCommerce's
179
- `main` on every push and nightly.
222
+ `GOCOMMERCE_TEST_DB` lets the b2b suite mark its test accounts' emails
223
+ confirmed — the engine confirms one only from a link it mails — and without it
224
+ those tests skip. Use a throwaway store. The suites skip, loudly, when there is
225
+ no engine. CI runs them against GoCommerce's `main` on every push and nightly,
226
+ along with the route-coverage check.
180
227
 
181
228
  ## Releasing
182
229