brainerce 2.2.0 → 2.3.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 +8090 -7920
- package/dist/index.d.mts +210 -43
- package/dist/index.d.ts +210 -43
- package/dist/index.js +236 -97
- package/dist/index.mjs +236 -97
- package/package.json +4 -3
package/dist/index.mjs
CHANGED
|
@@ -115,7 +115,7 @@ function isDevGuardsEnabled() {
|
|
|
115
115
|
}
|
|
116
116
|
|
|
117
117
|
// src/version.ts
|
|
118
|
-
var SDK_VERSION = "2.
|
|
118
|
+
var SDK_VERSION = "2.3.0";
|
|
119
119
|
|
|
120
120
|
// src/client.ts
|
|
121
121
|
var DEFAULT_BASE_URL = "https://api.brainerce.com";
|
|
@@ -837,10 +837,19 @@ var _BrainerceClient = class _BrainerceClient {
|
|
|
837
837
|
this.customerToken = null;
|
|
838
838
|
}
|
|
839
839
|
// -------------------- Private Methods --------------------
|
|
840
|
+
/**
|
|
841
|
+
* Turn an `idempotencyKey` option into the header the backend reads.
|
|
842
|
+
*
|
|
843
|
+
* Returns `undefined` when there is no key, so the header is absent rather
|
|
844
|
+
* than empty — the interceptor rejects a present-but-blank key with a 400.
|
|
845
|
+
*/
|
|
846
|
+
idempotencyHeaders(options) {
|
|
847
|
+
return options?.idempotencyKey ? { "Idempotency-Key": options.idempotencyKey } : void 0;
|
|
848
|
+
}
|
|
840
849
|
/**
|
|
841
850
|
* Make a request to the Admin API (requires apiKey)
|
|
842
851
|
*/
|
|
843
|
-
async adminRequest(method, path, body, queryParams, responseType = "json") {
|
|
852
|
+
async adminRequest(method, path, body, queryParams, responseType = "json", extraHeaders) {
|
|
844
853
|
if (!this.apiKey) {
|
|
845
854
|
throw new BrainerceError(
|
|
846
855
|
"This operation requires an API key. Initialize with apiKey instead of storeId.",
|
|
@@ -870,6 +879,11 @@ var _BrainerceClient = class _BrainerceClient {
|
|
|
870
879
|
if (this.locale) {
|
|
871
880
|
headers["Accept-Language"] = this.locale;
|
|
872
881
|
}
|
|
882
|
+
if (extraHeaders) {
|
|
883
|
+
for (const [key, value] of Object.entries(extraHeaders)) {
|
|
884
|
+
if (value) headers[key] = value;
|
|
885
|
+
}
|
|
886
|
+
}
|
|
873
887
|
for (let attempt = 0; attempt < 2; attempt++) {
|
|
874
888
|
const controller = new AbortController();
|
|
875
889
|
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
@@ -2194,21 +2208,25 @@ var _BrainerceClient = class _BrainerceClient {
|
|
|
2194
2208
|
);
|
|
2195
2209
|
}
|
|
2196
2210
|
/**
|
|
2197
|
-
* Publish a product to specific platforms
|
|
2211
|
+
* Publish a product to specific platforms.
|
|
2198
2212
|
*
|
|
2199
|
-
*
|
|
2200
|
-
*
|
|
2201
|
-
*
|
|
2202
|
-
*
|
|
2203
|
-
*
|
|
2213
|
+
* **Not callable.** The API-key `/v1` surface has no `products/:id/publish`
|
|
2214
|
+
* route. Platform publishing for products exists only on the dashboard
|
|
2215
|
+
* surface (`POST /api/products/:id/publish?storeId=`,
|
|
2216
|
+
* `products.controller.ts:556`), which resolves the acting user from a
|
|
2217
|
+
* dashboard session an API key does not carry. The generic trigger
|
|
2218
|
+
* `POST /v1/sync` answers `501 Not Implemented` and points at per-resource
|
|
2219
|
+
* publish endpoints — and products have none.
|
|
2220
|
+
*
|
|
2221
|
+
* {@link publishProductToSalesChannel} is a DIFFERENT operation: it controls
|
|
2222
|
+
* visibility on a vibe-coded storefront, not a push to an external platform.
|
|
2204
2223
|
*/
|
|
2205
2224
|
async publishProduct(productId, platforms) {
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
}
|
|
2225
|
+
void productId;
|
|
2226
|
+
void platforms;
|
|
2227
|
+
throw new BrainerceError(
|
|
2228
|
+
"publishProduct is not a route on the API-key /v1 surface. There is no products/:id/publish endpoint to call, so nothing was published; publish the product to a platform from the Brainerce dashboard. Note that publishProductToSalesChannel is a different operation \u2014 it controls vibe-coded storefront visibility, not an external-platform push.",
|
|
2229
|
+
400
|
|
2212
2230
|
);
|
|
2213
2231
|
}
|
|
2214
2232
|
// -------------------- Variants --------------------
|
|
@@ -4203,6 +4221,9 @@ var _BrainerceClient = class _BrainerceClient {
|
|
|
4203
4221
|
* flags reflect the live state. Call this on cart load if you want to
|
|
4204
4222
|
* surface drift to the customer before they reach checkout.
|
|
4205
4223
|
*
|
|
4224
|
+
* **Storefront and vibe-coded modes only.** There is no admin (`apiKey`)
|
|
4225
|
+
* route for this, so an admin-mode client throws instead of 404ing.
|
|
4226
|
+
*
|
|
4206
4227
|
* @example
|
|
4207
4228
|
* ```typescript
|
|
4208
4229
|
* const cart = await client.recalculateCart('cart_123');
|
|
@@ -4227,9 +4248,9 @@ var _BrainerceClient = class _BrainerceClient {
|
|
|
4227
4248
|
"cart"
|
|
4228
4249
|
);
|
|
4229
4250
|
}
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
|
|
4251
|
+
throw new BrainerceError(
|
|
4252
|
+
"recalculateCart is not a route on the API-key /v1 surface. There is no cart/:cartId/recalculate endpoint to call, so nothing was recalculated. Cart recalculation is a storefront operation \u2014 call it from a client constructed with `salesChannelId` (vibe-coded) or `storeId` (public storefront), where the route exists.",
|
|
4253
|
+
400
|
|
4233
4254
|
);
|
|
4234
4255
|
}
|
|
4235
4256
|
/**
|
|
@@ -4238,6 +4259,9 @@ var _BrainerceClient = class _BrainerceClient {
|
|
|
4238
4259
|
* subsequent `createCheckout` call will then succeed (it would otherwise
|
|
4239
4260
|
* throw `PRICE_DRIFT`).
|
|
4240
4261
|
*
|
|
4262
|
+
* **Storefront and vibe-coded modes only.** There is no admin (`apiKey`)
|
|
4263
|
+
* route for this, so an admin-mode client throws instead of 404ing.
|
|
4264
|
+
*
|
|
4241
4265
|
* @example
|
|
4242
4266
|
* ```typescript
|
|
4243
4267
|
* try {
|
|
@@ -4272,12 +4296,9 @@ var _BrainerceClient = class _BrainerceClient {
|
|
|
4272
4296
|
"cart"
|
|
4273
4297
|
);
|
|
4274
4298
|
}
|
|
4275
|
-
|
|
4276
|
-
|
|
4277
|
-
|
|
4278
|
-
`/api/v1/cart/${encodePathSegment(cartId)}/refresh-snapshots`
|
|
4279
|
-
),
|
|
4280
|
-
"cart"
|
|
4299
|
+
throw new BrainerceError(
|
|
4300
|
+
"refreshCartSnapshots is not a route on the API-key /v1 surface. There is no cart/:cartId/refresh-snapshots endpoint to call, so no price snapshots were refreshed. Snapshot refresh is a storefront operation \u2014 call it from a client constructed with `salesChannelId` (vibe-coded) or `storeId` (public storefront), where the route exists.",
|
|
4301
|
+
400
|
|
4281
4302
|
);
|
|
4282
4303
|
}
|
|
4283
4304
|
/**
|
|
@@ -5786,22 +5807,39 @@ var _BrainerceClient = class _BrainerceClient {
|
|
|
5786
5807
|
* screen or database query can recover it.
|
|
5787
5808
|
*
|
|
5788
5809
|
* A `note` is required. Refused when gift cards are switched off for the
|
|
5789
|
-
* store.
|
|
5810
|
+
* store.
|
|
5811
|
+
*
|
|
5812
|
+
* ⚠️ **Pass an `idempotencyKey`.** It is the ONLY recovery that exists here:
|
|
5813
|
+
* re-sending the identical request with the same key inside 24 hours replays
|
|
5814
|
+
* the cached response, code included. Without one, a retried timeout mints a
|
|
5815
|
+
* SECOND card and a second real liability. The key is sent as the
|
|
5816
|
+
* `Idempotency-Key` header; reuse the same value across retries of the same
|
|
5817
|
+
* logical issue, never a fresh random one.
|
|
5790
5818
|
*
|
|
5791
5819
|
* Requires `gift_cards:issue`.
|
|
5792
5820
|
*
|
|
5793
5821
|
* @example
|
|
5794
5822
|
* ```typescript
|
|
5795
|
-
* const card = await client.issueGiftCard(
|
|
5796
|
-
*
|
|
5797
|
-
*
|
|
5798
|
-
*
|
|
5799
|
-
*
|
|
5823
|
+
* const card = await client.issueGiftCard(
|
|
5824
|
+
* {
|
|
5825
|
+
* amount: '200.00',
|
|
5826
|
+
* note: 'Compensation for order #1042',
|
|
5827
|
+
* recipientEmail: 'dana@example.com',
|
|
5828
|
+
* },
|
|
5829
|
+
* { idempotencyKey: 'compensation-order-1042' }
|
|
5830
|
+
* );
|
|
5800
5831
|
* await sendToCustomer(card.plaintextCode); // your only chance
|
|
5801
5832
|
* ```
|
|
5802
5833
|
*/
|
|
5803
|
-
async issueGiftCard(data) {
|
|
5804
|
-
return this.adminRequest(
|
|
5834
|
+
async issueGiftCard(data, options) {
|
|
5835
|
+
return this.adminRequest(
|
|
5836
|
+
"POST",
|
|
5837
|
+
"/api/v1/gift-cards",
|
|
5838
|
+
data,
|
|
5839
|
+
void 0,
|
|
5840
|
+
"json",
|
|
5841
|
+
this.idempotencyHeaders(options)
|
|
5842
|
+
);
|
|
5805
5843
|
}
|
|
5806
5844
|
/**
|
|
5807
5845
|
* Re-issue a gift card onto a new code.
|
|
@@ -5814,15 +5852,21 @@ var _BrainerceClient = class _BrainerceClient {
|
|
|
5814
5852
|
* while a checkout holds value on the card. The original expiry carries
|
|
5815
5853
|
* forward, so this cannot be used to restart an expiry clock.
|
|
5816
5854
|
*
|
|
5817
|
-
* The new code is returned exactly once, under the same rules as issuance
|
|
5855
|
+
* The new code is returned exactly once, under the same rules as issuance —
|
|
5856
|
+
* so pass an `idempotencyKey` here for the same reason, and with the same
|
|
5857
|
+
* force: a retried timeout without one revokes the replacement it just made
|
|
5858
|
+
* and mints another.
|
|
5818
5859
|
*
|
|
5819
5860
|
* Requires `gift_cards:issue`.
|
|
5820
5861
|
*/
|
|
5821
|
-
async reissueGiftCard(giftCardId, note) {
|
|
5862
|
+
async reissueGiftCard(giftCardId, note, options) {
|
|
5822
5863
|
return this.adminRequest(
|
|
5823
5864
|
"POST",
|
|
5824
5865
|
`/api/v1/gift-cards/${encodePathSegment(giftCardId)}/reissue`,
|
|
5825
|
-
{ note }
|
|
5866
|
+
{ note },
|
|
5867
|
+
void 0,
|
|
5868
|
+
"json",
|
|
5869
|
+
this.idempotencyHeaders(options)
|
|
5826
5870
|
);
|
|
5827
5871
|
}
|
|
5828
5872
|
/**
|
|
@@ -5835,13 +5879,19 @@ var _BrainerceClient = class _BrainerceClient {
|
|
|
5835
5879
|
* A debit cannot take the balance below what live checkout holds have already
|
|
5836
5880
|
* reserved; that refusal names the held amount so you can act on it.
|
|
5837
5881
|
*
|
|
5882
|
+
* Pass an `idempotencyKey`: an adjustment is a relative move, so a retried
|
|
5883
|
+
* timeout without one applies the delta twice.
|
|
5884
|
+
*
|
|
5838
5885
|
* Requires `gift_cards:adjust`.
|
|
5839
5886
|
*/
|
|
5840
|
-
async adjustGiftCardBalance(giftCardId, delta, note) {
|
|
5887
|
+
async adjustGiftCardBalance(giftCardId, delta, note, options) {
|
|
5841
5888
|
return this.adminRequest(
|
|
5842
5889
|
"PATCH",
|
|
5843
5890
|
`/api/v1/gift-cards/${encodePathSegment(giftCardId)}/adjust`,
|
|
5844
|
-
{ delta, note }
|
|
5891
|
+
{ delta, note },
|
|
5892
|
+
void 0,
|
|
5893
|
+
"json",
|
|
5894
|
+
this.idempotencyHeaders(options)
|
|
5845
5895
|
);
|
|
5846
5896
|
}
|
|
5847
5897
|
/**
|
|
@@ -5854,11 +5904,14 @@ var _BrainerceClient = class _BrainerceClient {
|
|
|
5854
5904
|
*
|
|
5855
5905
|
* Requires `gift_cards:write`.
|
|
5856
5906
|
*/
|
|
5857
|
-
async setGiftCardStatus(giftCardId, status) {
|
|
5907
|
+
async setGiftCardStatus(giftCardId, status, options) {
|
|
5858
5908
|
return this.adminRequest(
|
|
5859
5909
|
"PATCH",
|
|
5860
5910
|
`/api/v1/gift-cards/${encodePathSegment(giftCardId)}/status`,
|
|
5861
|
-
{ status }
|
|
5911
|
+
{ status },
|
|
5912
|
+
void 0,
|
|
5913
|
+
"json",
|
|
5914
|
+
this.idempotencyHeaders(options)
|
|
5862
5915
|
);
|
|
5863
5916
|
}
|
|
5864
5917
|
/**
|
|
@@ -5874,11 +5927,15 @@ var _BrainerceClient = class _BrainerceClient {
|
|
|
5874
5927
|
*
|
|
5875
5928
|
* Requires `gift_cards:write`.
|
|
5876
5929
|
*/
|
|
5877
|
-
async bulkSetGiftCardStatus(giftCardIds, status) {
|
|
5878
|
-
return this.adminRequest(
|
|
5879
|
-
|
|
5880
|
-
status
|
|
5881
|
-
|
|
5930
|
+
async bulkSetGiftCardStatus(giftCardIds, status, options) {
|
|
5931
|
+
return this.adminRequest(
|
|
5932
|
+
"PATCH",
|
|
5933
|
+
"/api/v1/gift-cards/bulk/status",
|
|
5934
|
+
{ giftCardIds, status },
|
|
5935
|
+
void 0,
|
|
5936
|
+
"json",
|
|
5937
|
+
this.idempotencyHeaders(options)
|
|
5938
|
+
);
|
|
5882
5939
|
}
|
|
5883
5940
|
// ==========================================================================
|
|
5884
5941
|
// Donations
|
|
@@ -6287,6 +6344,9 @@ var _BrainerceClient = class _BrainerceClient {
|
|
|
6287
6344
|
/**
|
|
6288
6345
|
* Set delivery type on checkout (shipping or pickup).
|
|
6289
6346
|
*
|
|
6347
|
+
* **Storefront and vibe-coded modes only.** There is no admin (`apiKey`)
|
|
6348
|
+
* route for this, so an admin-mode client throws instead of 404ing.
|
|
6349
|
+
*
|
|
6290
6350
|
* @example
|
|
6291
6351
|
* ```typescript
|
|
6292
6352
|
* const checkout = await client.setDeliveryType('checkout_123', 'pickup');
|
|
@@ -6311,12 +6371,9 @@ var _BrainerceClient = class _BrainerceClient {
|
|
|
6311
6371
|
}
|
|
6312
6372
|
);
|
|
6313
6373
|
}
|
|
6314
|
-
|
|
6315
|
-
"
|
|
6316
|
-
|
|
6317
|
-
{
|
|
6318
|
-
deliveryType
|
|
6319
|
-
}
|
|
6374
|
+
throw new BrainerceError(
|
|
6375
|
+
"setDeliveryType is not a route on the API-key /v1 surface. There is no checkout/:checkoutId/delivery-type endpoint to call, so the delivery type was not changed. Set it from the storefront session that owns the checkout \u2014 a client constructed with `salesChannelId` (vibe-coded) or `storeId` (public storefront) \u2014 or from the Brainerce dashboard.",
|
|
6376
|
+
400
|
|
6320
6377
|
);
|
|
6321
6378
|
}
|
|
6322
6379
|
/**
|
|
@@ -6324,6 +6381,9 @@ var _BrainerceClient = class _BrainerceClient {
|
|
|
6324
6381
|
* This sets the delivery type to "pickup", records customer info, and prepares for payment.
|
|
6325
6382
|
* Equivalent to setShippingAddress + selectShippingMethod for delivery orders.
|
|
6326
6383
|
*
|
|
6384
|
+
* **Storefront and vibe-coded modes only.** There is no admin (`apiKey`)
|
|
6385
|
+
* route for this, so an admin-mode client throws instead of 404ing.
|
|
6386
|
+
*
|
|
6327
6387
|
* @example
|
|
6328
6388
|
* ```typescript
|
|
6329
6389
|
* const checkout = await client.selectPickupLocation('checkout_123', {
|
|
@@ -6350,10 +6410,9 @@ var _BrainerceClient = class _BrainerceClient {
|
|
|
6350
6410
|
data
|
|
6351
6411
|
);
|
|
6352
6412
|
}
|
|
6353
|
-
|
|
6354
|
-
"
|
|
6355
|
-
|
|
6356
|
-
data
|
|
6413
|
+
throw new BrainerceError(
|
|
6414
|
+
"selectPickupLocation is not a route on the API-key /v1 surface. There is no checkout/:checkoutId/pickup-location endpoint to call, so no pickup location was selected. Select it from the storefront session that owns the checkout \u2014 a client constructed with `salesChannelId` (vibe-coded) or `storeId` (public storefront) \u2014 or from the Brainerce dashboard.",
|
|
6415
|
+
400
|
|
6357
6416
|
);
|
|
6358
6417
|
}
|
|
6359
6418
|
/**
|
|
@@ -7678,13 +7737,17 @@ var _BrainerceClient = class _BrainerceClient {
|
|
|
7678
7737
|
* lifetime earned, the program's display config, earned milestone `badges`,
|
|
7679
7738
|
* and the `paidMembership` subscription state (null for free members).
|
|
7680
7739
|
* Requires customerToken. Only available in storefront mode. `program` is
|
|
7681
|
-
* null when the store has no loyalty program.
|
|
7740
|
+
* null when the store has no loyalty program. `pointsBalance` excludes points
|
|
7741
|
+
* still inside the return window - those are in `pendingPoints`, and a panel
|
|
7742
|
+
* that ignores them shows a shopper 0 the day they order.
|
|
7682
7743
|
*
|
|
7683
7744
|
* @example
|
|
7684
7745
|
* ```typescript
|
|
7685
7746
|
* client.setCustomerToken(auth.token);
|
|
7686
7747
|
* const status = await client.getLoyaltyStatus();
|
|
7687
7748
|
* if (status.enrolled) console.log(`${status.pointsBalance} ${status.program?.pointsName}`);
|
|
7749
|
+
* // Points from an order just placed are in pendingPoints, NOT pointsBalance.
|
|
7750
|
+
* if (status.pendingPoints > 0) console.log(`+${status.pendingPoints} on ${status.pendingPointsConfirmAt}`);
|
|
7688
7751
|
* status.badges?.forEach((b) => console.log(`🏅 ${b.name}`));
|
|
7689
7752
|
* if (status.paidMembership?.status === 'ACTIVE') showPremiumPerks(status.paidMembership.plan);
|
|
7690
7753
|
* ```
|
|
@@ -8531,11 +8594,28 @@ var _BrainerceClient = class _BrainerceClient {
|
|
|
8531
8594
|
return this.adminRequest("POST", "/api/v1/tags", data);
|
|
8532
8595
|
}
|
|
8533
8596
|
/**
|
|
8534
|
-
* Update an existing tag
|
|
8535
|
-
*
|
|
8597
|
+
* Update an existing tag.
|
|
8598
|
+
*
|
|
8599
|
+
* **Not callable.** The API-key `/v1` surface serves `GET`, `POST` and
|
|
8600
|
+
* `DELETE` on tags (`external-api.controller.ts:3276`, `:3310`, `:3331`) but
|
|
8601
|
+
* no update verb — `PATCH /api/v1/tags/:id` 404'd silently. Tag editing lives
|
|
8602
|
+
* only on the dashboard surface (`PATCH /api/stores/:storeId/tags/:id`,
|
|
8603
|
+
* `tags.controller.ts:127`), which needs a `storeId` in the path that this
|
|
8604
|
+
* signature does not carry, and resolves the acting user from a dashboard
|
|
8605
|
+
* session an API key does not have.
|
|
8606
|
+
*
|
|
8607
|
+
* Edit the tag in the Brainerce dashboard. {@link deleteTag} +
|
|
8608
|
+
* {@link createTag} is NOT an equivalent workaround: it drops the tag's
|
|
8609
|
+
* product assignments, and `CreateTagDto` has no `translations` field, so any
|
|
8610
|
+
* per-locale names are lost too.
|
|
8536
8611
|
*/
|
|
8537
8612
|
async updateTag(tagId, data) {
|
|
8538
|
-
|
|
8613
|
+
void tagId;
|
|
8614
|
+
void data;
|
|
8615
|
+
throw new BrainerceError(
|
|
8616
|
+
"updateTag is not a route on the API-key /v1 surface. Tags are served there for read, create and delete only, so the tag was not changed; edit it in the Brainerce dashboard. Deleting and recreating the tag is not equivalent \u2014 it drops the product assignments and the translations.",
|
|
8617
|
+
400
|
|
8618
|
+
);
|
|
8539
8619
|
}
|
|
8540
8620
|
/**
|
|
8541
8621
|
* Delete a tag
|
|
@@ -8633,24 +8713,41 @@ var _BrainerceClient = class _BrainerceClient {
|
|
|
8633
8713
|
);
|
|
8634
8714
|
}
|
|
8635
8715
|
/**
|
|
8636
|
-
* Update an attribute option
|
|
8637
|
-
*
|
|
8716
|
+
* Update an attribute option.
|
|
8717
|
+
*
|
|
8718
|
+
* **Not callable.** The API-key `/v1` surface serves attribute options for
|
|
8719
|
+
* list and create only (`external-api.controller.ts:3517`, `:3543`); there is
|
|
8720
|
+
* no per-option route, so this 404'd silently. Editing an option lives on the
|
|
8721
|
+
* dashboard surface (`PUT /api/stores/:storeId/attributes/:id/options/:optionId`,
|
|
8722
|
+
* `attributes.controller.ts:132` — note it is `PUT` there, not `PATCH`), which
|
|
8723
|
+
* needs a path `storeId` this signature does not carry.
|
|
8724
|
+
*
|
|
8725
|
+
* Edit the option in the Brainerce dashboard.
|
|
8638
8726
|
*/
|
|
8639
8727
|
async updateAttributeOption(attributeId, optionId, data) {
|
|
8640
|
-
|
|
8641
|
-
|
|
8642
|
-
|
|
8643
|
-
|
|
8728
|
+
void attributeId;
|
|
8729
|
+
void optionId;
|
|
8730
|
+
void data;
|
|
8731
|
+
throw new BrainerceError(
|
|
8732
|
+
"updateAttributeOption is not a route on the API-key /v1 surface. Attribute options are served there for list and create only, so the option was not changed; edit it in the Brainerce dashboard.",
|
|
8733
|
+
400
|
|
8644
8734
|
);
|
|
8645
8735
|
}
|
|
8646
8736
|
/**
|
|
8647
|
-
* Delete an attribute option
|
|
8648
|
-
*
|
|
8737
|
+
* Delete an attribute option.
|
|
8738
|
+
*
|
|
8739
|
+
* **Not callable.** Same gap as {@link updateAttributeOption}: the `/v1`
|
|
8740
|
+
* surface has no per-option route. Deleting an option lives on the dashboard
|
|
8741
|
+
* surface (`DELETE /api/stores/:storeId/attributes/:id/options/:optionId`,
|
|
8742
|
+
* `attributes.controller.ts:145`), which needs a path `storeId` this signature
|
|
8743
|
+
* does not carry.
|
|
8649
8744
|
*/
|
|
8650
8745
|
async deleteAttributeOption(attributeId, optionId) {
|
|
8651
|
-
|
|
8652
|
-
|
|
8653
|
-
|
|
8746
|
+
void attributeId;
|
|
8747
|
+
void optionId;
|
|
8748
|
+
throw new BrainerceError(
|
|
8749
|
+
"deleteAttributeOption is not a route on the API-key /v1 surface. Attribute options are served there for list and create only, so nothing was deleted; delete the option in the Brainerce dashboard.",
|
|
8750
|
+
400
|
|
8654
8751
|
);
|
|
8655
8752
|
}
|
|
8656
8753
|
// -------------------- Modifier Groups (Admin) --------------------
|
|
@@ -9473,25 +9570,48 @@ var _BrainerceClient = class _BrainerceClient {
|
|
|
9473
9570
|
// Products/Coupons. When no publishes exist for an entity, it remains
|
|
9474
9571
|
// visible to all vibe-coded sites of the store (legacy default).
|
|
9475
9572
|
/**
|
|
9476
|
-
* Publish a metafield definition to a
|
|
9477
|
-
*
|
|
9478
|
-
*
|
|
9479
|
-
*
|
|
9480
|
-
*
|
|
9573
|
+
* Publish a metafield definition to a sales channel (admin mode).
|
|
9574
|
+
*
|
|
9575
|
+
* **Not callable.** This asked for `publish-vibe-coded`, which is a
|
|
9576
|
+
* deprecated backend alias, not the canonical route. The canonical spelling
|
|
9577
|
+
* is `publish-sales-channel`, and the `/v1` surface serves it for products
|
|
9578
|
+
* (`external-api.controller.ts:862`), coupons (`:947`), customers (`:1548`),
|
|
9579
|
+
* categories (`:3039`), brands (`:3211`) and tags (`:3349`) — but NOT for
|
|
9580
|
+
* metafield definitions. Both spellings 404 there.
|
|
9581
|
+
*
|
|
9582
|
+
* The operation exists only on the dashboard surface
|
|
9583
|
+
* (`POST /api/stores/:storeId/metafield-definitions/:id/publish-sales-channel`,
|
|
9584
|
+
* `metafields.controller.ts:190`), which needs a path `storeId` this signature
|
|
9585
|
+
* does not carry.
|
|
9586
|
+
*
|
|
9587
|
+
* Publish the definition to a sales channel from the Brainerce dashboard. A
|
|
9588
|
+
* definition with no publishes stays visible to every sales channel of the
|
|
9589
|
+
* store, so leaving it unpublished is the permissive default, not a lockout.
|
|
9481
9590
|
*/
|
|
9482
9591
|
async publishMetafieldDefinitionToVibeCodedSite(definitionId, vibeCodedConnectionId) {
|
|
9483
|
-
|
|
9484
|
-
|
|
9485
|
-
|
|
9486
|
-
|
|
9592
|
+
void definitionId;
|
|
9593
|
+
void vibeCodedConnectionId;
|
|
9594
|
+
throw new BrainerceError(
|
|
9595
|
+
"publishMetafieldDefinitionToVibeCodedSite is not a route on the API-key /v1 surface. Per-sales-channel publishing is served there for products, coupons, customers, categories, brands and tags, but not for metafield definitions, so nothing was published; publish it in the Brainerce dashboard. A definition with no publishes remains visible to every sales channel of the store.",
|
|
9596
|
+
400
|
|
9487
9597
|
);
|
|
9488
9598
|
}
|
|
9489
|
-
/**
|
|
9599
|
+
/**
|
|
9600
|
+
* Unpublish a metafield definition from a sales channel (admin mode).
|
|
9601
|
+
*
|
|
9602
|
+
* **Not callable.** Same gap as
|
|
9603
|
+
* {@link publishMetafieldDefinitionToVibeCodedSite} — the `/v1` surface
|
|
9604
|
+
* carries no per-sales-channel routes for metafield definitions under either
|
|
9605
|
+
* the canonical `unpublish-sales-channel` spelling or the deprecated
|
|
9606
|
+
* `unpublish-vibe-coded` alias. The dashboard route is
|
|
9607
|
+
* `metafields.controller.ts:217`.
|
|
9608
|
+
*/
|
|
9490
9609
|
async unpublishMetafieldDefinitionFromVibeCodedSite(definitionId, vibeCodedConnectionId) {
|
|
9491
|
-
|
|
9492
|
-
|
|
9493
|
-
|
|
9494
|
-
|
|
9610
|
+
void definitionId;
|
|
9611
|
+
void vibeCodedConnectionId;
|
|
9612
|
+
throw new BrainerceError(
|
|
9613
|
+
"unpublishMetafieldDefinitionFromVibeCodedSite is not a route on the API-key /v1 surface. Per-sales-channel publishing is served there for products, coupons, customers, categories, brands and tags, but not for metafield definitions, so nothing was unpublished; unpublish it in the Brainerce dashboard.",
|
|
9614
|
+
400
|
|
9495
9615
|
);
|
|
9496
9616
|
}
|
|
9497
9617
|
/**
|
|
@@ -9637,10 +9757,11 @@ var _BrainerceClient = class _BrainerceClient {
|
|
|
9637
9757
|
* ```
|
|
9638
9758
|
*/
|
|
9639
9759
|
async setDefinitionProducts(definitionId, data) {
|
|
9640
|
-
|
|
9641
|
-
|
|
9642
|
-
|
|
9643
|
-
|
|
9760
|
+
void definitionId;
|
|
9761
|
+
void data;
|
|
9762
|
+
throw new BrainerceError(
|
|
9763
|
+
"setDefinitionProducts is not a route on the API-key /v1 surface. There is no metafield-definitions/:id/products endpoint to call, so the definition's product list was not changed; set it in the Brainerce dashboard.",
|
|
9764
|
+
400
|
|
9644
9765
|
);
|
|
9645
9766
|
}
|
|
9646
9767
|
// -------------------- Metafields: Product Values --------------------
|
|
@@ -9686,24 +9807,41 @@ var _BrainerceClient = class _BrainerceClient {
|
|
|
9686
9807
|
// -------------------- Product Customization Fields (Admin) --------------------
|
|
9687
9808
|
/**
|
|
9688
9809
|
* Get customization fields assigned to a product.
|
|
9689
|
-
*
|
|
9810
|
+
*
|
|
9811
|
+
* **Not callable.** The API-key `/v1` surface has no
|
|
9812
|
+
* `metafield-definitions/products/:productId/customization-fields` route, so
|
|
9813
|
+
* this 404'd silently. It exists only on the dashboard surface
|
|
9814
|
+
* (`GET /api/stores/:storeId/metafield-definitions/products/:productId/customization-fields`,
|
|
9815
|
+
* `metafields.controller.ts:277`), which needs a path `storeId` this signature
|
|
9816
|
+
* does not carry.
|
|
9817
|
+
*
|
|
9818
|
+
* {@link getProductMetafields} is the closest working call — it returns the
|
|
9819
|
+
* metafield VALUES stored on a product over
|
|
9820
|
+
* `GET /api/v1/products/:productId/metafields`, not the customer-input field
|
|
9821
|
+
* definitions attached to it.
|
|
9690
9822
|
*/
|
|
9691
9823
|
async getProductCustomizationFields(productId) {
|
|
9692
|
-
|
|
9693
|
-
|
|
9694
|
-
|
|
9824
|
+
void productId;
|
|
9825
|
+
throw new BrainerceError(
|
|
9826
|
+
"getProductCustomizationFields is not a route on the API-key /v1 surface. There is no metafield-definitions/products/:productId/customization-fields endpoint to call; read the assignments in the Brainerce dashboard. getProductMetafields returns the product's stored metafield values, which is a different thing.",
|
|
9827
|
+
400
|
|
9695
9828
|
);
|
|
9696
9829
|
}
|
|
9697
9830
|
/**
|
|
9698
9831
|
* Set customization fields for a product (replaces all existing assignments).
|
|
9699
|
-
*
|
|
9700
|
-
*
|
|
9832
|
+
*
|
|
9833
|
+
* **Not callable.** Same gap as {@link getProductCustomizationFields}: the
|
|
9834
|
+
* `/v1` surface carries no customization-field routes. The dashboard route is
|
|
9835
|
+
* `PATCH /api/stores/:storeId/metafield-definitions/products/:productId/customization-fields`
|
|
9836
|
+
* (`metafields.controller.ts:298`), which needs a path `storeId` this
|
|
9837
|
+
* signature does not carry.
|
|
9701
9838
|
*/
|
|
9702
9839
|
async setProductCustomizationFields(productId, definitionIds) {
|
|
9703
|
-
|
|
9704
|
-
|
|
9705
|
-
|
|
9706
|
-
|
|
9840
|
+
void productId;
|
|
9841
|
+
void definitionIds;
|
|
9842
|
+
throw new BrainerceError(
|
|
9843
|
+
"setProductCustomizationFields is not a route on the API-key /v1 surface. There is no metafield-definitions/products/:productId/customization-fields endpoint to call, so the assignments were not changed; set them in the Brainerce dashboard.",
|
|
9844
|
+
400
|
|
9707
9845
|
);
|
|
9708
9846
|
}
|
|
9709
9847
|
/**
|
|
@@ -11098,6 +11236,7 @@ function buildProductJsonLd(product, opts) {
|
|
|
11098
11236
|
const inv = product.inventory;
|
|
11099
11237
|
const availability = !inv ? "https://schema.org/InStock" : inv.inStock ?? (inv.available ?? 0) > 0 ? "https://schema.org/InStock" : inv.canPurchase ? "https://schema.org/BackOrder" : "https://schema.org/OutOfStock";
|
|
11100
11238
|
const isVariable = product.type === "VARIABLE" && product.priceMin && product.priceMax;
|
|
11239
|
+
const omitOffer = product.type === "KIT";
|
|
11101
11240
|
const itemCondition = "https://schema.org/NewCondition";
|
|
11102
11241
|
const shippingDetails = (opts.shipping ?? []).filter((z) => z.amount !== null).map((z) => ({
|
|
11103
11242
|
"@type": "OfferShippingDetails",
|
|
@@ -11160,7 +11299,7 @@ function buildProductJsonLd(product, opts) {
|
|
|
11160
11299
|
...product.gtin ? { gtin: product.gtin } : {},
|
|
11161
11300
|
...product.mpn ? { mpn: product.mpn } : {},
|
|
11162
11301
|
...brand ? { brand: { "@type": "Brand", name: brand } } : {},
|
|
11163
|
-
offers: offer,
|
|
11302
|
+
...omitOffer ? {} : { offers: offer },
|
|
11164
11303
|
// Google policy: never emit an empty/zero rating block. bestRating /
|
|
11165
11304
|
// worstRating make the 1-5 scale explicit so aggregators can't misread
|
|
11166
11305
|
// a 4.8 on an assumed 0-10 scale.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "brainerce",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.0",
|
|
4
4
|
"description": "Official SDK for building e-commerce storefronts with Brainerce Platform. Perfect for vibe-coded sites, AI-built stores (Cursor, Lovable, v0), and custom storefronts.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -19,7 +19,8 @@
|
|
|
19
19
|
},
|
|
20
20
|
"files": [
|
|
21
21
|
"dist",
|
|
22
|
-
"README.md"
|
|
22
|
+
"README.md",
|
|
23
|
+
"LICENSE"
|
|
23
24
|
],
|
|
24
25
|
"scripts": {
|
|
25
26
|
"build": "node ../../scripts/sync-sdk-version.js && tsup src/index.ts --format cjs,esm --dts && tsup src/bot/index.ts --format cjs,esm --dts --out-dir dist/bot && tsup src/bot/bootstrap.ts --format iife --minify --out-dir dist/bot",
|
|
@@ -30,7 +31,7 @@
|
|
|
30
31
|
"test:watch": "vitest",
|
|
31
32
|
"release": "pnpm build && node ../../scripts/publish-workspace-package.js .",
|
|
32
33
|
"check:routes": "node ../../scripts/check-sdk-routes.js",
|
|
33
|
-
"prepublishOnly": "node ../../scripts/check-sdk-routes.js && node ../../scripts/check-publishable.js ./package.json
|
|
34
|
+
"prepublishOnly": "node ../../scripts/check-sdk-routes.js && pnpm build && node ../../scripts/check-publishable.js ./package.json",
|
|
34
35
|
"sync:version": "node ../../scripts/sync-sdk-version.js"
|
|
35
36
|
},
|
|
36
37
|
"keywords": [
|