brainerce 2.1.0 → 2.2.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/README.md +367 -65
- package/dist/index.d.mts +305 -13
- package/dist/index.d.ts +305 -13
- package/dist/index.js +249 -71
- package/dist/index.mjs +249 -71
- package/package.json +85 -84
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.0
|
|
118
|
+
var SDK_VERSION = "2.2.0";
|
|
119
119
|
|
|
120
120
|
// src/client.ts
|
|
121
121
|
var DEFAULT_BASE_URL = "https://api.brainerce.com";
|
|
@@ -361,7 +361,7 @@ var _BrainerceClient = class _BrainerceClient {
|
|
|
361
361
|
* Works in all three SDK modes (vibe-coded, storefront, admin):
|
|
362
362
|
* - **Public reads** (`get`, `list`, `getBySlug`): work in any mode.
|
|
363
363
|
* - **Write operations** (`create`, `update`, `publish`, `unpublish`,
|
|
364
|
-
* `remove`): admin mode only — they call `/api/
|
|
364
|
+
* `remove`): admin mode only — they call `/api/content/...` with
|
|
365
365
|
* the API key. Calling from storefront / vibe-coded mode throws.
|
|
366
366
|
*
|
|
367
367
|
* **Default key:** every type has `'main'` as its universal default key.
|
|
@@ -398,7 +398,7 @@ var _BrainerceClient = class _BrainerceClient {
|
|
|
398
398
|
this.content = (() => {
|
|
399
399
|
const DEFAULT_KEY = "main";
|
|
400
400
|
const publicGetPath = (type, key) => `/content/${encodeURIComponent(type)}/${encodeURIComponent(key)}`;
|
|
401
|
-
const adminBase = () => "/api/
|
|
401
|
+
const adminBase = () => "/api/content";
|
|
402
402
|
const publicGet = async (type, key, locale) => {
|
|
403
403
|
const query = locale ? { locale } : void 0;
|
|
404
404
|
const path = publicGetPath(type, key);
|
|
@@ -2018,11 +2018,9 @@ var _BrainerceClient = class _BrainerceClient {
|
|
|
2018
2018
|
queryParams
|
|
2019
2019
|
);
|
|
2020
2020
|
}
|
|
2021
|
-
|
|
2022
|
-
"
|
|
2023
|
-
|
|
2024
|
-
void 0,
|
|
2025
|
-
queryParams
|
|
2021
|
+
throw new BrainerceError(
|
|
2022
|
+
"getSearchSuggestions is a storefront API. There is no admin suggestions endpoint \u2014 construct the client with `salesChannelId` or `storeId` to use it, or call getProducts({ search }) in admin mode.",
|
|
2023
|
+
400
|
|
2026
2024
|
);
|
|
2027
2025
|
}
|
|
2028
2026
|
/**
|
|
@@ -5723,6 +5721,166 @@ var _BrainerceClient = class _BrainerceClient {
|
|
|
5723
5721
|
return this.adminRequest("POST", "/api/v1/gift-cards/balance", { code });
|
|
5724
5722
|
}
|
|
5725
5723
|
// ==========================================================================
|
|
5724
|
+
// Gift cards — administration (API key only)
|
|
5725
|
+
//
|
|
5726
|
+
// Full programmatic management, unlike Shopify, which requires you to ask
|
|
5727
|
+
// their support for the equivalent scope. The gate here is the SCOPE the
|
|
5728
|
+
// merchant granted your key, so the separation matters: `gift_cards:issue`
|
|
5729
|
+
// mints stored value and `gift_cards:adjust` rewrites a balance, and neither
|
|
5730
|
+
// is implied by `gift_cards:read`. Ask for the least your integration needs.
|
|
5731
|
+
//
|
|
5732
|
+
// Every call reaches the same service the dashboard uses, so the rules hold
|
|
5733
|
+
// identically: a note is mandatory on anything that moves value, a debit
|
|
5734
|
+
// cannot cross what live checkout holds have reserved, and there is no delete
|
|
5735
|
+
// anywhere — the ledger is append-only.
|
|
5736
|
+
// ==========================================================================
|
|
5737
|
+
/**
|
|
5738
|
+
* List gift cards.
|
|
5739
|
+
*
|
|
5740
|
+
* `search` matches the LAST FOUR of a code or part of a recipient email. It
|
|
5741
|
+
* cannot match a full code: only an HMAC is stored, so there is nothing to
|
|
5742
|
+
* search against.
|
|
5743
|
+
*
|
|
5744
|
+
* Requires `gift_cards:read`.
|
|
5745
|
+
*/
|
|
5746
|
+
async listGiftCards(params) {
|
|
5747
|
+
const q = new URLSearchParams();
|
|
5748
|
+
if (params?.page) q.set("page", String(params.page));
|
|
5749
|
+
if (params?.limit) q.set("limit", String(params.limit));
|
|
5750
|
+
if (params?.filter) q.set("filter", params.filter);
|
|
5751
|
+
if (params?.search) q.set("search", params.search);
|
|
5752
|
+
const qs = q.toString();
|
|
5753
|
+
return this.adminRequest(
|
|
5754
|
+
"GET",
|
|
5755
|
+
`/api/v1/gift-cards${qs ? `?${qs}` : ""}`
|
|
5756
|
+
);
|
|
5757
|
+
}
|
|
5758
|
+
/**
|
|
5759
|
+
* Outstanding gift card liability, per currency.
|
|
5760
|
+
*
|
|
5761
|
+
* This is the month-end number. Read `byCurrency` if the store sells in more
|
|
5762
|
+
* than one — currencies are never summed together.
|
|
5763
|
+
*
|
|
5764
|
+
* Requires `gift_cards:read`.
|
|
5765
|
+
*/
|
|
5766
|
+
async getGiftCardLiability() {
|
|
5767
|
+
return this.adminRequest("GET", "/api/v1/gift-cards/liability");
|
|
5768
|
+
}
|
|
5769
|
+
/**
|
|
5770
|
+
* One gift card with its full ledger.
|
|
5771
|
+
*
|
|
5772
|
+
* Requires `gift_cards:read`.
|
|
5773
|
+
*/
|
|
5774
|
+
async getGiftCard(giftCardId) {
|
|
5775
|
+
return this.adminRequest(
|
|
5776
|
+
"GET",
|
|
5777
|
+
`/api/v1/gift-cards/${encodePathSegment(giftCardId)}`
|
|
5778
|
+
);
|
|
5779
|
+
}
|
|
5780
|
+
/**
|
|
5781
|
+
* Issue a gift card.
|
|
5782
|
+
*
|
|
5783
|
+
* ⚠️ **The code comes back exactly once.** It is stored only as an HMAC, so
|
|
5784
|
+
* this response is the only time it exists in readable form anywhere. Persist
|
|
5785
|
+
* it or deliver it before you discard the response — no later call, dashboard
|
|
5786
|
+
* screen or database query can recover it.
|
|
5787
|
+
*
|
|
5788
|
+
* A `note` is required. Refused when gift cards are switched off for the
|
|
5789
|
+
* store. Pass an `Idempotency-Key` header to make a retry safe.
|
|
5790
|
+
*
|
|
5791
|
+
* Requires `gift_cards:issue`.
|
|
5792
|
+
*
|
|
5793
|
+
* @example
|
|
5794
|
+
* ```typescript
|
|
5795
|
+
* const card = await client.issueGiftCard({
|
|
5796
|
+
* amount: '200.00',
|
|
5797
|
+
* note: 'Compensation for order #1042',
|
|
5798
|
+
* recipientEmail: 'dana@example.com',
|
|
5799
|
+
* });
|
|
5800
|
+
* await sendToCustomer(card.plaintextCode); // your only chance
|
|
5801
|
+
* ```
|
|
5802
|
+
*/
|
|
5803
|
+
async issueGiftCard(data) {
|
|
5804
|
+
return this.adminRequest("POST", "/api/v1/gift-cards", data);
|
|
5805
|
+
}
|
|
5806
|
+
/**
|
|
5807
|
+
* Re-issue a gift card onto a new code.
|
|
5808
|
+
*
|
|
5809
|
+
* The answer to a customer losing their code. Mints a new code, moves the
|
|
5810
|
+
* WHOLE balance to it, and REVOKES the old card.
|
|
5811
|
+
*
|
|
5812
|
+
* **This is not a resend.** The old code stops working the moment this
|
|
5813
|
+
* returns — if the customer still holds a printed card, it dies. Refused
|
|
5814
|
+
* while a checkout holds value on the card. The original expiry carries
|
|
5815
|
+
* forward, so this cannot be used to restart an expiry clock.
|
|
5816
|
+
*
|
|
5817
|
+
* The new code is returned exactly once, under the same rules as issuance.
|
|
5818
|
+
*
|
|
5819
|
+
* Requires `gift_cards:issue`.
|
|
5820
|
+
*/
|
|
5821
|
+
async reissueGiftCard(giftCardId, note) {
|
|
5822
|
+
return this.adminRequest(
|
|
5823
|
+
"POST",
|
|
5824
|
+
`/api/v1/gift-cards/${encodePathSegment(giftCardId)}/reissue`,
|
|
5825
|
+
{ note }
|
|
5826
|
+
);
|
|
5827
|
+
}
|
|
5828
|
+
/**
|
|
5829
|
+
* Adjust a gift card balance.
|
|
5830
|
+
*
|
|
5831
|
+
* `delta` is a SIGNED decimal string: `"25.00"` adds, `"-25.00"` takes away.
|
|
5832
|
+
* The `note` is required and is written to the ledger permanently — it is the
|
|
5833
|
+
* row a finance review reads a year from now.
|
|
5834
|
+
*
|
|
5835
|
+
* A debit cannot take the balance below what live checkout holds have already
|
|
5836
|
+
* reserved; that refusal names the held amount so you can act on it.
|
|
5837
|
+
*
|
|
5838
|
+
* Requires `gift_cards:adjust`.
|
|
5839
|
+
*/
|
|
5840
|
+
async adjustGiftCardBalance(giftCardId, delta, note) {
|
|
5841
|
+
return this.adminRequest(
|
|
5842
|
+
"PATCH",
|
|
5843
|
+
`/api/v1/gift-cards/${encodePathSegment(giftCardId)}/adjust`,
|
|
5844
|
+
{ delta, note }
|
|
5845
|
+
);
|
|
5846
|
+
}
|
|
5847
|
+
/**
|
|
5848
|
+
* Enable, disable or revoke one gift card.
|
|
5849
|
+
*
|
|
5850
|
+
* Deliberately does NOT touch live holds: a checkout that already reserved
|
|
5851
|
+
* value settles normally, because pulling it out from under a shopper
|
|
5852
|
+
* mid-payment would strand a provider charge already in flight. Disabling
|
|
5853
|
+
* stops NEW holds, which is what "off" actually means.
|
|
5854
|
+
*
|
|
5855
|
+
* Requires `gift_cards:write`.
|
|
5856
|
+
*/
|
|
5857
|
+
async setGiftCardStatus(giftCardId, status) {
|
|
5858
|
+
return this.adminRequest(
|
|
5859
|
+
"PATCH",
|
|
5860
|
+
`/api/v1/gift-cards/${encodePathSegment(giftCardId)}/status`,
|
|
5861
|
+
{ status }
|
|
5862
|
+
);
|
|
5863
|
+
}
|
|
5864
|
+
/**
|
|
5865
|
+
* Disable or reactivate many gift cards at once.
|
|
5866
|
+
*
|
|
5867
|
+
* `REVOKED` is not accepted here — it belongs to re-issue, which moves the
|
|
5868
|
+
* balance to a replacement first. Revoking in bulk would strand balances with
|
|
5869
|
+
* nowhere to go. Cards already revoked are skipped, so the returned count is
|
|
5870
|
+
* the honest one and may be lower than the ids you sent.
|
|
5871
|
+
*
|
|
5872
|
+
* There is no bulk delete, here or anywhere: the ledger is append-only and a
|
|
5873
|
+
* card may carry a statutory retention life.
|
|
5874
|
+
*
|
|
5875
|
+
* Requires `gift_cards:write`.
|
|
5876
|
+
*/
|
|
5877
|
+
async bulkSetGiftCardStatus(giftCardIds, status) {
|
|
5878
|
+
return this.adminRequest("PATCH", "/api/v1/gift-cards/bulk/status", {
|
|
5879
|
+
giftCardIds,
|
|
5880
|
+
status
|
|
5881
|
+
});
|
|
5882
|
+
}
|
|
5883
|
+
// ==========================================================================
|
|
5726
5884
|
// Donations
|
|
5727
5885
|
// ==========================================================================
|
|
5728
5886
|
/**
|
|
@@ -5865,10 +6023,7 @@ var _BrainerceClient = class _BrainerceClient {
|
|
|
5865
6023
|
"/checkouts/shipping-destinations"
|
|
5866
6024
|
);
|
|
5867
6025
|
}
|
|
5868
|
-
return this.adminRequest(
|
|
5869
|
-
"GET",
|
|
5870
|
-
"/api/v1/checkouts/shipping-destinations"
|
|
5871
|
-
);
|
|
6026
|
+
return this.adminRequest("GET", "/api/checkouts/shipping-destinations");
|
|
5872
6027
|
}
|
|
5873
6028
|
/**
|
|
5874
6029
|
* Set shipping address on checkout (includes customer email).
|
|
@@ -6127,7 +6282,7 @@ var _BrainerceClient = class _BrainerceClient {
|
|
|
6127
6282
|
if (this.storeId && !this.apiKey) {
|
|
6128
6283
|
return this.storefrontRequest("GET", "/pickup-locations");
|
|
6129
6284
|
}
|
|
6130
|
-
return this.adminRequest("GET", "/api/
|
|
6285
|
+
return this.adminRequest("GET", "/api/checkouts/pickup-locations");
|
|
6131
6286
|
}
|
|
6132
6287
|
/**
|
|
6133
6288
|
* Set delivery type on checkout (shipping or pickup).
|
|
@@ -9101,10 +9256,7 @@ var _BrainerceClient = class _BrainerceClient {
|
|
|
9101
9256
|
* ```
|
|
9102
9257
|
*/
|
|
9103
9258
|
async applyTaxPreset(presetKey) {
|
|
9104
|
-
return this.adminRequest(
|
|
9105
|
-
"POST",
|
|
9106
|
-
`/api/v1/tax/presets/${encodePathSegment(presetKey)}/apply`
|
|
9107
|
-
);
|
|
9259
|
+
return this.adminRequest("POST", `/api/v1/tax/presets/${encodePathSegment(presetKey)}/apply`);
|
|
9108
9260
|
}
|
|
9109
9261
|
/**
|
|
9110
9262
|
* Get a single tax rate by ID
|
|
@@ -9734,6 +9886,27 @@ var _BrainerceClient = class _BrainerceClient {
|
|
|
9734
9886
|
}
|
|
9735
9887
|
// -------------------- Store Team Management (Admin) --------------------
|
|
9736
9888
|
// Store-level team management. Each store has its own team with roles and permissions.
|
|
9889
|
+
/**
|
|
9890
|
+
* Every store-level team operation is dashboard-only.
|
|
9891
|
+
*
|
|
9892
|
+
* `store-team.controller.ts:53` carries `DashboardOnlyGuard`, which rejects
|
|
9893
|
+
* `api_key` and `app_installation` principals outright, so no SDK caller can
|
|
9894
|
+
* reach these however the URL is spelled. They additionally pointed at
|
|
9895
|
+
* `/api/v1/stores/:storeId/team*`, and `@Controller('v1')`
|
|
9896
|
+
* (external-api.controller.ts:181) has no `stores` root — so what they
|
|
9897
|
+
* actually returned was a 404, not the 403 you would expect from the guard.
|
|
9898
|
+
*
|
|
9899
|
+
* Throwing beats either status code: a 404 reads as "wrong id" and a 403 as
|
|
9900
|
+
* "missing permission", and both send the caller looking for a fix that does
|
|
9901
|
+
* not exist. Use the account-level `getTeamMembers()` family, or the
|
|
9902
|
+
* dashboard.
|
|
9903
|
+
*/
|
|
9904
|
+
dashboardOnlyTeamOperation(operation) {
|
|
9905
|
+
throw new BrainerceError(
|
|
9906
|
+
`${operation} is a dashboard-only operation. Store-level team management sits behind DashboardOnlyGuard, which rejects API-key principals, so there is no SDK path to it in any mode. Use the account-level team methods (getTeamMembers, inviteTeamMember, ...) or the Brainerce dashboard.`,
|
|
9907
|
+
403
|
|
9908
|
+
);
|
|
9909
|
+
}
|
|
9737
9910
|
/**
|
|
9738
9911
|
* Get the team for a specific store (members + pending invitations)
|
|
9739
9912
|
* Requires Admin mode (apiKey) and MANAGE_TEAM permission
|
|
@@ -9743,11 +9916,8 @@ var _BrainerceClient = class _BrainerceClient {
|
|
|
9743
9916
|
* const { members, invitations } = await client.getStoreTeam('store_id');
|
|
9744
9917
|
* ```
|
|
9745
9918
|
*/
|
|
9746
|
-
async getStoreTeam(
|
|
9747
|
-
return this.
|
|
9748
|
-
"GET",
|
|
9749
|
-
`/api/v1/stores/${encodePathSegment(storeId)}/team`
|
|
9750
|
-
);
|
|
9919
|
+
async getStoreTeam(_storeId) {
|
|
9920
|
+
return this.dashboardOnlyTeamOperation("getStoreTeam");
|
|
9751
9921
|
}
|
|
9752
9922
|
/**
|
|
9753
9923
|
* Invite a new member to a store
|
|
@@ -9764,12 +9934,8 @@ var _BrainerceClient = class _BrainerceClient {
|
|
|
9764
9934
|
* });
|
|
9765
9935
|
* ```
|
|
9766
9936
|
*/
|
|
9767
|
-
async inviteStoreMember(
|
|
9768
|
-
return this.
|
|
9769
|
-
"POST",
|
|
9770
|
-
`/api/v1/stores/${encodePathSegment(storeId)}/team/invite`,
|
|
9771
|
-
data
|
|
9772
|
-
);
|
|
9937
|
+
async inviteStoreMember(_storeId, _data) {
|
|
9938
|
+
return this.dashboardOnlyTeamOperation("inviteStoreMember");
|
|
9773
9939
|
}
|
|
9774
9940
|
/**
|
|
9775
9941
|
* Update a store team member's role and/or permissions
|
|
@@ -9786,12 +9952,8 @@ var _BrainerceClient = class _BrainerceClient {
|
|
|
9786
9952
|
* });
|
|
9787
9953
|
* ```
|
|
9788
9954
|
*/
|
|
9789
|
-
async updateStoreMember(
|
|
9790
|
-
return this.
|
|
9791
|
-
"PATCH",
|
|
9792
|
-
`/api/v1/stores/${encodePathSegment(storeId)}/team/${encodePathSegment(memberId)}`,
|
|
9793
|
-
data
|
|
9794
|
-
);
|
|
9955
|
+
async updateStoreMember(_storeId, _memberId, _data) {
|
|
9956
|
+
return this.dashboardOnlyTeamOperation("updateStoreMember");
|
|
9795
9957
|
}
|
|
9796
9958
|
/**
|
|
9797
9959
|
* Replace the set of vibe-coded sales channels a store member is restricted to.
|
|
@@ -9812,42 +9974,29 @@ var _BrainerceClient = class _BrainerceClient {
|
|
|
9812
9974
|
* });
|
|
9813
9975
|
* ```
|
|
9814
9976
|
*/
|
|
9815
|
-
async updateStoreMemberSalesChannels(
|
|
9816
|
-
return this.
|
|
9817
|
-
"PATCH",
|
|
9818
|
-
`/api/v1/stores/${encodePathSegment(storeId)}/team/${encodePathSegment(memberId)}/sales-channels`,
|
|
9819
|
-
data
|
|
9820
|
-
);
|
|
9977
|
+
async updateStoreMemberSalesChannels(_storeId, _memberId, _data) {
|
|
9978
|
+
return this.dashboardOnlyTeamOperation("updateStoreMemberSalesChannels");
|
|
9821
9979
|
}
|
|
9822
9980
|
/**
|
|
9823
9981
|
* Remove a member from a store team
|
|
9824
9982
|
* Requires Admin mode (apiKey) and MANAGE_TEAM permission
|
|
9825
9983
|
*/
|
|
9826
|
-
async removeStoreMember(
|
|
9827
|
-
|
|
9828
|
-
"DELETE",
|
|
9829
|
-
`/api/v1/stores/${encodePathSegment(storeId)}/team/${encodePathSegment(memberId)}`
|
|
9830
|
-
);
|
|
9984
|
+
async removeStoreMember(_storeId, _memberId) {
|
|
9985
|
+
return this.dashboardOnlyTeamOperation("removeStoreMember");
|
|
9831
9986
|
}
|
|
9832
9987
|
/**
|
|
9833
9988
|
* Resend a store invitation email
|
|
9834
9989
|
* Requires Admin mode (apiKey) and MANAGE_TEAM permission
|
|
9835
9990
|
*/
|
|
9836
|
-
async resendStoreInvitation(
|
|
9837
|
-
return this.
|
|
9838
|
-
"POST",
|
|
9839
|
-
`/api/v1/stores/${encodePathSegment(storeId)}/team/invitations/${encodePathSegment(invitationId)}/resend`
|
|
9840
|
-
);
|
|
9991
|
+
async resendStoreInvitation(_storeId, _invitationId) {
|
|
9992
|
+
return this.dashboardOnlyTeamOperation("resendStoreInvitation");
|
|
9841
9993
|
}
|
|
9842
9994
|
/**
|
|
9843
9995
|
* Revoke a store invitation
|
|
9844
9996
|
* Requires Admin mode (apiKey) and MANAGE_TEAM permission
|
|
9845
9997
|
*/
|
|
9846
|
-
async revokeStoreInvitation(
|
|
9847
|
-
|
|
9848
|
-
"DELETE",
|
|
9849
|
-
`/api/v1/stores/${encodePathSegment(storeId)}/team/invitations/${encodePathSegment(invitationId)}`
|
|
9850
|
-
);
|
|
9998
|
+
async revokeStoreInvitation(_storeId, _invitationId) {
|
|
9999
|
+
return this.dashboardOnlyTeamOperation("revokeStoreInvitation");
|
|
9851
10000
|
}
|
|
9852
10001
|
/**
|
|
9853
10002
|
* Get public invitation details by token (no auth required)
|
|
@@ -9856,7 +10005,7 @@ var _BrainerceClient = class _BrainerceClient {
|
|
|
9856
10005
|
async getStoreInvitationByToken(token) {
|
|
9857
10006
|
return this.request(
|
|
9858
10007
|
"GET",
|
|
9859
|
-
`/api/
|
|
10008
|
+
`/api/store-invitations/${encodePathSegment(token)}`
|
|
9860
10009
|
);
|
|
9861
10010
|
}
|
|
9862
10011
|
/**
|
|
@@ -9864,9 +10013,9 @@ var _BrainerceClient = class _BrainerceClient {
|
|
|
9864
10013
|
* Requires Admin mode (apiKey)
|
|
9865
10014
|
*/
|
|
9866
10015
|
async acceptStoreInvitation(token) {
|
|
9867
|
-
|
|
9868
|
-
"
|
|
9869
|
-
|
|
10016
|
+
throw new BrainerceError(
|
|
10017
|
+
"acceptStoreInvitation requires a dashboard session belonging to the invited user: the invitation is matched against the email address of that user, which an API key does not have. Send the invitee to the invitation link instead.",
|
|
10018
|
+
403
|
|
9870
10019
|
);
|
|
9871
10020
|
}
|
|
9872
10021
|
/**
|
|
@@ -9883,7 +10032,7 @@ var _BrainerceClient = class _BrainerceClient {
|
|
|
9883
10032
|
* ```
|
|
9884
10033
|
*/
|
|
9885
10034
|
async getMyStores() {
|
|
9886
|
-
return this.
|
|
10035
|
+
return this.dashboardOnlyUserContext("getMyStores");
|
|
9887
10036
|
}
|
|
9888
10037
|
/**
|
|
9889
10038
|
* Get the current user's resolved permissions for a specific store
|
|
@@ -9897,10 +10046,23 @@ var _BrainerceClient = class _BrainerceClient {
|
|
|
9897
10046
|
* }
|
|
9898
10047
|
* ```
|
|
9899
10048
|
*/
|
|
9900
|
-
async getMyStorePermissions(
|
|
9901
|
-
return this.
|
|
9902
|
-
|
|
9903
|
-
|
|
10049
|
+
async getMyStorePermissions(_storeId) {
|
|
10050
|
+
return this.dashboardOnlyUserContext("getMyStorePermissions");
|
|
10051
|
+
}
|
|
10052
|
+
/**
|
|
10053
|
+
* `/me/*` answers "who am I and what can I reach", which only a real user can
|
|
10054
|
+
* ask. `UserContextController` (store-team.controller.ts:246) is guarded by
|
|
10055
|
+
* `DashboardOnlyGuard` for a load-bearing reason its own G16 comment spells
|
|
10056
|
+
* out: both routes resolve access purely from `@CurrentUserId()`, which is
|
|
10057
|
+
* `undefined` for an api_key principal, so the store filter would be stripped
|
|
10058
|
+
* and every store on the platform returned. The guard is the control. These
|
|
10059
|
+
* also pointed at `/api/v1/me/*`, which no controller serves, so the observed
|
|
10060
|
+
* failure was a 404 rather than the guard's 403.
|
|
10061
|
+
*/
|
|
10062
|
+
dashboardOnlyUserContext(operation) {
|
|
10063
|
+
throw new BrainerceError(
|
|
10064
|
+
`${operation} resolves the CURRENT USER, so it requires a dashboard session and is rejected for API-key principals by design. An API key is already scoped to one store: read it with getStore(), and read the permissions of a member from getStoreTeam() in the dashboard.`,
|
|
10065
|
+
403
|
|
9904
10066
|
);
|
|
9905
10067
|
}
|
|
9906
10068
|
// -------------------- Email Settings & Templates (Admin) --------------------
|
|
@@ -10043,7 +10205,7 @@ var _BrainerceClient = class _BrainerceClient {
|
|
|
10043
10205
|
* Requires Admin mode (apiKey)
|
|
10044
10206
|
*/
|
|
10045
10207
|
async getSyncConflicts() {
|
|
10046
|
-
return this.
|
|
10208
|
+
return this.syncConflictsNotImplemented("getSyncConflicts");
|
|
10047
10209
|
}
|
|
10048
10210
|
/**
|
|
10049
10211
|
* Resolve a sync conflict
|
|
@@ -10053,12 +10215,28 @@ var _BrainerceClient = class _BrainerceClient {
|
|
|
10053
10215
|
* @param resolution - 'MERGE' to link to existing product, 'CREATE_NEW' to create new product
|
|
10054
10216
|
*/
|
|
10055
10217
|
async resolveSyncConflict(conflictId, resolution) {
|
|
10056
|
-
|
|
10057
|
-
|
|
10058
|
-
|
|
10059
|
-
|
|
10060
|
-
|
|
10061
|
-
|
|
10218
|
+
void conflictId;
|
|
10219
|
+
void resolution;
|
|
10220
|
+
return this.syncConflictsNotImplemented("resolveSyncConflict");
|
|
10221
|
+
}
|
|
10222
|
+
/**
|
|
10223
|
+
* Sync conflicts were never implemented on the server.
|
|
10224
|
+
*
|
|
10225
|
+
* There is no `sync-conflict` route anywhere in the backend — not under
|
|
10226
|
+
* `@Controller('v1')`, not on any other controller. These two methods have
|
|
10227
|
+
* called a URL that has never existed, and `SyncConflict` /
|
|
10228
|
+
* `SyncConflictResolution` / `ResolveSyncConflictDto` are exported types with
|
|
10229
|
+
* no producer. The METAFIELD conflict siblings below are real
|
|
10230
|
+
* (external-api.controller.ts:4788, :4802) and are easy to mistake for these.
|
|
10231
|
+
*
|
|
10232
|
+
* Kept as throwing stubs rather than deleted: removing exported methods from a
|
|
10233
|
+
* published package is a breaking change, and a caller who has been swallowing
|
|
10234
|
+
* a 404 deserves to be told why.
|
|
10235
|
+
*/
|
|
10236
|
+
syncConflictsNotImplemented(operation) {
|
|
10237
|
+
throw new BrainerceError(
|
|
10238
|
+
`${operation} is not implemented: the platform exposes no sync-conflict endpoint. If you are looking for metafield sync conflicts, use getMetafieldConflicts() / resolveMetafieldConflict().`,
|
|
10239
|
+
501
|
|
10062
10240
|
);
|
|
10063
10241
|
}
|
|
10064
10242
|
// -------------------- Metafield Conflicts (Admin) --------------------
|
package/package.json
CHANGED
|
@@ -1,84 +1,85 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "brainerce",
|
|
3
|
-
"version": "2.
|
|
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
|
-
"main": "dist/index.js",
|
|
6
|
-
"module": "dist/index.mjs",
|
|
7
|
-
"types": "dist/index.d.ts",
|
|
8
|
-
"exports": {
|
|
9
|
-
".": {
|
|
10
|
-
"types": "./dist/index.d.ts",
|
|
11
|
-
"require": "./dist/index.js",
|
|
12
|
-
"import": "./dist/index.mjs"
|
|
13
|
-
},
|
|
14
|
-
"./bot": {
|
|
15
|
-
"types": "./dist/bot/index.d.ts",
|
|
16
|
-
"require": "./dist/bot/index.js",
|
|
17
|
-
"import": "./dist/bot/index.mjs"
|
|
18
|
-
}
|
|
19
|
-
},
|
|
20
|
-
"files": [
|
|
21
|
-
"dist",
|
|
22
|
-
"README.md"
|
|
23
|
-
],
|
|
24
|
-
"scripts": {
|
|
25
|
-
"build": "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",
|
|
26
|
-
"type-check": "tsc --noEmit",
|
|
27
|
-
"dev": "tsup src/index.ts --format cjs,esm --dts --watch",
|
|
28
|
-
"lint": "eslint \"src/**/*.ts\"",
|
|
29
|
-
"test": "vitest run",
|
|
30
|
-
"test:watch": "vitest",
|
|
31
|
-
"release": "pnpm build && node ../../scripts/publish-workspace-package.js .",
|
|
32
|
-
"
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
"
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
"
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
"@
|
|
70
|
-
"@typescript-eslint/
|
|
71
|
-
"eslint": "^
|
|
72
|
-
"
|
|
73
|
-
"
|
|
74
|
-
"
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "brainerce",
|
|
3
|
+
"version": "2.2.0",
|
|
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
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"require": "./dist/index.js",
|
|
12
|
+
"import": "./dist/index.mjs"
|
|
13
|
+
},
|
|
14
|
+
"./bot": {
|
|
15
|
+
"types": "./dist/bot/index.d.ts",
|
|
16
|
+
"require": "./dist/bot/index.js",
|
|
17
|
+
"import": "./dist/bot/index.mjs"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist",
|
|
22
|
+
"README.md"
|
|
23
|
+
],
|
|
24
|
+
"scripts": {
|
|
25
|
+
"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",
|
|
26
|
+
"type-check": "tsc --noEmit",
|
|
27
|
+
"dev": "tsup src/index.ts --format cjs,esm --dts --watch",
|
|
28
|
+
"lint": "eslint \"src/**/*.ts\"",
|
|
29
|
+
"test": "vitest run",
|
|
30
|
+
"test:watch": "vitest",
|
|
31
|
+
"release": "pnpm build && node ../../scripts/publish-workspace-package.js .",
|
|
32
|
+
"check:routes": "node ../../scripts/check-sdk-routes.js",
|
|
33
|
+
"prepublishOnly": "node ../../scripts/check-sdk-routes.js && node ../../scripts/check-publishable.js ./package.json && pnpm build",
|
|
34
|
+
"sync:version": "node ../../scripts/sync-sdk-version.js"
|
|
35
|
+
},
|
|
36
|
+
"keywords": [
|
|
37
|
+
"brainerce",
|
|
38
|
+
"e-commerce",
|
|
39
|
+
"ecommerce",
|
|
40
|
+
"sdk",
|
|
41
|
+
"vibe-coding",
|
|
42
|
+
"vibe-coded",
|
|
43
|
+
"ai-commerce",
|
|
44
|
+
"storefront",
|
|
45
|
+
"headless-commerce",
|
|
46
|
+
"multi-platform",
|
|
47
|
+
"shopify",
|
|
48
|
+
"tiktok",
|
|
49
|
+
"cursor",
|
|
50
|
+
"lovable",
|
|
51
|
+
"v0",
|
|
52
|
+
"cart",
|
|
53
|
+
"checkout",
|
|
54
|
+
"products",
|
|
55
|
+
"sync"
|
|
56
|
+
],
|
|
57
|
+
"author": "Brainerce",
|
|
58
|
+
"license": "MIT",
|
|
59
|
+
"repository": {
|
|
60
|
+
"type": "git",
|
|
61
|
+
"url": "https://github.com/brainerce/brainerce.git",
|
|
62
|
+
"directory": "packages/sdk"
|
|
63
|
+
},
|
|
64
|
+
"homepage": "https://brainerce.com",
|
|
65
|
+
"bugs": {
|
|
66
|
+
"url": "https://github.com/brainerce/brainerce/issues"
|
|
67
|
+
},
|
|
68
|
+
"devDependencies": {
|
|
69
|
+
"@types/node": "^25.0.3",
|
|
70
|
+
"@typescript-eslint/eslint-plugin": "^8.50.1",
|
|
71
|
+
"@typescript-eslint/parser": "^8.50.1",
|
|
72
|
+
"eslint": "^9.39.2",
|
|
73
|
+
"tsup": "^8.0.0",
|
|
74
|
+
"typescript": "^5.3.0",
|
|
75
|
+
"vitest": "^1.0.0"
|
|
76
|
+
},
|
|
77
|
+
"peerDependencies": {
|
|
78
|
+
"typescript": ">=4.7.0"
|
|
79
|
+
},
|
|
80
|
+
"peerDependenciesMeta": {
|
|
81
|
+
"typescript": {
|
|
82
|
+
"optional": true
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|