brainerce 1.33.0 → 1.34.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 +27 -0
- package/dist/index.d.mts +91 -0
- package/dist/index.d.ts +91 -0
- package/dist/index.js +117 -0
- package/dist/index.mjs +117 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -409,6 +409,33 @@ The `create-brainerce-store` scaffold ships ready-made components (`<Announcemen
|
|
|
409
409
|
|
|
410
410
|
Full guide: [Core Integration "Content"](https://brainerce.com/docs/integration/core#content). Advanced patterns (channel scoping, custom fields, translations, admin writes): [Optional Features "Content"](https://brainerce.com/docs/integration/optional). Validation + sanitize rules: [Rules & Reference "Content"](https://brainerce.com/docs/integration/rules).
|
|
411
411
|
|
|
412
|
+
### Blog
|
|
413
|
+
|
|
414
|
+
Merchants publish blog posts in **Content → Blog**. Storefronts choose their own URL scheme — render posts at `/blog/[slug]`, `/articles/[slug]`, or whatever fits the brand.
|
|
415
|
+
|
|
416
|
+
```typescript
|
|
417
|
+
// List published posts (any SDK mode)
|
|
418
|
+
const { data: posts, meta } = await client.blog.getPosts({ page: 1, limit: 10 });
|
|
419
|
+
|
|
420
|
+
// Filter by category or tag
|
|
421
|
+
const { data: news } = await client.blog.getPosts({ category: 'news' });
|
|
422
|
+
const { data: tips } = await client.blog.getPosts({ tag: 'tutorial' });
|
|
423
|
+
|
|
424
|
+
// Fetch one by slug — returns null on 404
|
|
425
|
+
const post = await client.blog.getPost(params.slug);
|
|
426
|
+
if (!post) notFound();
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
**Security**: `post.content` is merchant-authored HTML. Always sanitize before rendering:
|
|
430
|
+
|
|
431
|
+
```tsx
|
|
432
|
+
import DOMPurify from 'isomorphic-dompurify';
|
|
433
|
+
const safeHtml = DOMPurify.sanitize(post.content);
|
|
434
|
+
return <div dangerouslySetInnerHTML={{ __html: safeHtml }} className="prose" />;
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
**Scheduling**: A post is visible once `status === 'PUBLISHED'` and `publishedAt <= now()`. Set a future `publishedAt` when publishing to schedule — no cron needed.
|
|
438
|
+
|
|
412
439
|
---
|
|
413
440
|
|
|
414
441
|
## Common Mistakes to Avoid
|
package/dist/index.d.mts
CHANGED
|
@@ -5168,6 +5168,61 @@ interface ModifierValidationError {
|
|
|
5168
5168
|
/** Modifier the error belongs to (when applicable). */
|
|
5169
5169
|
modifierId?: string;
|
|
5170
5170
|
}
|
|
5171
|
+
type BlogPostStatus = 'DRAFT' | 'SCHEDULED' | 'PUBLISHED';
|
|
5172
|
+
interface BlogPost {
|
|
5173
|
+
id: string;
|
|
5174
|
+
storeId: string;
|
|
5175
|
+
title: string;
|
|
5176
|
+
slug: string;
|
|
5177
|
+
category?: string;
|
|
5178
|
+
content: string;
|
|
5179
|
+
excerpt?: string;
|
|
5180
|
+
coverImageUrl?: string;
|
|
5181
|
+
coverImageAlt?: string;
|
|
5182
|
+
author?: string;
|
|
5183
|
+
tags: string[];
|
|
5184
|
+
metadata: Record<string, unknown>;
|
|
5185
|
+
status: BlogPostStatus;
|
|
5186
|
+
publishedAt?: string;
|
|
5187
|
+
seoTitle?: string;
|
|
5188
|
+
seoDescription?: string;
|
|
5189
|
+
ogImageUrl?: string;
|
|
5190
|
+
createdAt: string;
|
|
5191
|
+
updatedAt: string;
|
|
5192
|
+
}
|
|
5193
|
+
interface CreateBlogPostInput {
|
|
5194
|
+
title: string;
|
|
5195
|
+
slug?: string;
|
|
5196
|
+
category?: string;
|
|
5197
|
+
content?: string;
|
|
5198
|
+
excerpt?: string;
|
|
5199
|
+
coverImageUrl?: string;
|
|
5200
|
+
coverImageAlt?: string;
|
|
5201
|
+
author?: string;
|
|
5202
|
+
tags?: string[];
|
|
5203
|
+
metadata?: Record<string, unknown>;
|
|
5204
|
+
status?: BlogPostStatus;
|
|
5205
|
+
publishedAt?: string | null;
|
|
5206
|
+
seoTitle?: string;
|
|
5207
|
+
seoDescription?: string;
|
|
5208
|
+
ogImageUrl?: string;
|
|
5209
|
+
}
|
|
5210
|
+
type UpdateBlogPostInput = Partial<CreateBlogPostInput>;
|
|
5211
|
+
interface BlogPostListParams {
|
|
5212
|
+
page?: number;
|
|
5213
|
+
limit?: number;
|
|
5214
|
+
category?: string;
|
|
5215
|
+
tag?: string;
|
|
5216
|
+
}
|
|
5217
|
+
interface BlogPostListResponse {
|
|
5218
|
+
data: BlogPost[];
|
|
5219
|
+
meta: {
|
|
5220
|
+
page: number;
|
|
5221
|
+
limit: number;
|
|
5222
|
+
total: number;
|
|
5223
|
+
totalPages: number;
|
|
5224
|
+
};
|
|
5225
|
+
}
|
|
5171
5226
|
interface BrainerceApiError {
|
|
5172
5227
|
statusCode: number;
|
|
5173
5228
|
message: string;
|
|
@@ -6637,6 +6692,42 @@ declare class BrainerceClient {
|
|
|
6637
6692
|
/** Hard delete the row. Admin mode only. */
|
|
6638
6693
|
remove: (id: string) => Promise<void>;
|
|
6639
6694
|
};
|
|
6695
|
+
/**
|
|
6696
|
+
* Read and manage blog posts.
|
|
6697
|
+
*
|
|
6698
|
+
* ```typescript
|
|
6699
|
+
* // Storefront / vibe-coded: list published posts
|
|
6700
|
+
* const { data: posts } = await brainerce.blog.getPosts({ category: 'news' });
|
|
6701
|
+
*
|
|
6702
|
+
* // Fetch one by slug
|
|
6703
|
+
* const post = await brainerce.blog.getPost('my-first-post');
|
|
6704
|
+
*
|
|
6705
|
+
* // Admin: create a draft
|
|
6706
|
+
* const draft = await brainerce.blog.create({ title: 'Hello World' });
|
|
6707
|
+
* ```
|
|
6708
|
+
*/
|
|
6709
|
+
blog: {
|
|
6710
|
+
/**
|
|
6711
|
+
* List published posts. Works in all modes.
|
|
6712
|
+
* Filters: `category`, `tag`, `page`, `limit`.
|
|
6713
|
+
*/
|
|
6714
|
+
getPosts: (params?: BlogPostListParams) => Promise<BlogPostListResponse>;
|
|
6715
|
+
/**
|
|
6716
|
+
* Fetch one published post by its slug. Returns `null` on 404.
|
|
6717
|
+
* Works in all modes.
|
|
6718
|
+
*/
|
|
6719
|
+
getPost: (slug: string) => Promise<BlogPost | null>;
|
|
6720
|
+
/** Create a blog post in DRAFT status. Admin mode only. */
|
|
6721
|
+
create: (input: CreateBlogPostInput) => Promise<BlogPost>;
|
|
6722
|
+
/** Update a blog post by ID. Admin mode only. */
|
|
6723
|
+
update: (id: string, input: UpdateBlogPostInput) => Promise<BlogPost>;
|
|
6724
|
+
/** Transition status → PUBLISHED (sets publishedAt = now if unset). Admin mode only. */
|
|
6725
|
+
publish: (id: string) => Promise<BlogPost>;
|
|
6726
|
+
/** Transition status PUBLISHED → DRAFT. Admin mode only. */
|
|
6727
|
+
unpublish: (id: string) => Promise<BlogPost>;
|
|
6728
|
+
/** Hard-delete a blog post. Admin mode only. */
|
|
6729
|
+
remove: (id: string) => Promise<void>;
|
|
6730
|
+
};
|
|
6640
6731
|
/**
|
|
6641
6732
|
* Submit a contact inquiry from a storefront contact form.
|
|
6642
6733
|
*
|
package/dist/index.d.ts
CHANGED
|
@@ -5168,6 +5168,61 @@ interface ModifierValidationError {
|
|
|
5168
5168
|
/** Modifier the error belongs to (when applicable). */
|
|
5169
5169
|
modifierId?: string;
|
|
5170
5170
|
}
|
|
5171
|
+
type BlogPostStatus = 'DRAFT' | 'SCHEDULED' | 'PUBLISHED';
|
|
5172
|
+
interface BlogPost {
|
|
5173
|
+
id: string;
|
|
5174
|
+
storeId: string;
|
|
5175
|
+
title: string;
|
|
5176
|
+
slug: string;
|
|
5177
|
+
category?: string;
|
|
5178
|
+
content: string;
|
|
5179
|
+
excerpt?: string;
|
|
5180
|
+
coverImageUrl?: string;
|
|
5181
|
+
coverImageAlt?: string;
|
|
5182
|
+
author?: string;
|
|
5183
|
+
tags: string[];
|
|
5184
|
+
metadata: Record<string, unknown>;
|
|
5185
|
+
status: BlogPostStatus;
|
|
5186
|
+
publishedAt?: string;
|
|
5187
|
+
seoTitle?: string;
|
|
5188
|
+
seoDescription?: string;
|
|
5189
|
+
ogImageUrl?: string;
|
|
5190
|
+
createdAt: string;
|
|
5191
|
+
updatedAt: string;
|
|
5192
|
+
}
|
|
5193
|
+
interface CreateBlogPostInput {
|
|
5194
|
+
title: string;
|
|
5195
|
+
slug?: string;
|
|
5196
|
+
category?: string;
|
|
5197
|
+
content?: string;
|
|
5198
|
+
excerpt?: string;
|
|
5199
|
+
coverImageUrl?: string;
|
|
5200
|
+
coverImageAlt?: string;
|
|
5201
|
+
author?: string;
|
|
5202
|
+
tags?: string[];
|
|
5203
|
+
metadata?: Record<string, unknown>;
|
|
5204
|
+
status?: BlogPostStatus;
|
|
5205
|
+
publishedAt?: string | null;
|
|
5206
|
+
seoTitle?: string;
|
|
5207
|
+
seoDescription?: string;
|
|
5208
|
+
ogImageUrl?: string;
|
|
5209
|
+
}
|
|
5210
|
+
type UpdateBlogPostInput = Partial<CreateBlogPostInput>;
|
|
5211
|
+
interface BlogPostListParams {
|
|
5212
|
+
page?: number;
|
|
5213
|
+
limit?: number;
|
|
5214
|
+
category?: string;
|
|
5215
|
+
tag?: string;
|
|
5216
|
+
}
|
|
5217
|
+
interface BlogPostListResponse {
|
|
5218
|
+
data: BlogPost[];
|
|
5219
|
+
meta: {
|
|
5220
|
+
page: number;
|
|
5221
|
+
limit: number;
|
|
5222
|
+
total: number;
|
|
5223
|
+
totalPages: number;
|
|
5224
|
+
};
|
|
5225
|
+
}
|
|
5171
5226
|
interface BrainerceApiError {
|
|
5172
5227
|
statusCode: number;
|
|
5173
5228
|
message: string;
|
|
@@ -6637,6 +6692,42 @@ declare class BrainerceClient {
|
|
|
6637
6692
|
/** Hard delete the row. Admin mode only. */
|
|
6638
6693
|
remove: (id: string) => Promise<void>;
|
|
6639
6694
|
};
|
|
6695
|
+
/**
|
|
6696
|
+
* Read and manage blog posts.
|
|
6697
|
+
*
|
|
6698
|
+
* ```typescript
|
|
6699
|
+
* // Storefront / vibe-coded: list published posts
|
|
6700
|
+
* const { data: posts } = await brainerce.blog.getPosts({ category: 'news' });
|
|
6701
|
+
*
|
|
6702
|
+
* // Fetch one by slug
|
|
6703
|
+
* const post = await brainerce.blog.getPost('my-first-post');
|
|
6704
|
+
*
|
|
6705
|
+
* // Admin: create a draft
|
|
6706
|
+
* const draft = await brainerce.blog.create({ title: 'Hello World' });
|
|
6707
|
+
* ```
|
|
6708
|
+
*/
|
|
6709
|
+
blog: {
|
|
6710
|
+
/**
|
|
6711
|
+
* List published posts. Works in all modes.
|
|
6712
|
+
* Filters: `category`, `tag`, `page`, `limit`.
|
|
6713
|
+
*/
|
|
6714
|
+
getPosts: (params?: BlogPostListParams) => Promise<BlogPostListResponse>;
|
|
6715
|
+
/**
|
|
6716
|
+
* Fetch one published post by its slug. Returns `null` on 404.
|
|
6717
|
+
* Works in all modes.
|
|
6718
|
+
*/
|
|
6719
|
+
getPost: (slug: string) => Promise<BlogPost | null>;
|
|
6720
|
+
/** Create a blog post in DRAFT status. Admin mode only. */
|
|
6721
|
+
create: (input: CreateBlogPostInput) => Promise<BlogPost>;
|
|
6722
|
+
/** Update a blog post by ID. Admin mode only. */
|
|
6723
|
+
update: (id: string, input: UpdateBlogPostInput) => Promise<BlogPost>;
|
|
6724
|
+
/** Transition status → PUBLISHED (sets publishedAt = now if unset). Admin mode only. */
|
|
6725
|
+
publish: (id: string) => Promise<BlogPost>;
|
|
6726
|
+
/** Transition status PUBLISHED → DRAFT. Admin mode only. */
|
|
6727
|
+
unpublish: (id: string) => Promise<BlogPost>;
|
|
6728
|
+
/** Hard-delete a blog post. Admin mode only. */
|
|
6729
|
+
remove: (id: string) => Promise<void>;
|
|
6730
|
+
};
|
|
6640
6731
|
/**
|
|
6641
6732
|
* Submit a contact inquiry from a storefront contact form.
|
|
6642
6733
|
*
|
package/dist/index.js
CHANGED
|
@@ -489,6 +489,120 @@ var BrainerceClient = class {
|
|
|
489
489
|
remove: removeById
|
|
490
490
|
};
|
|
491
491
|
})();
|
|
492
|
+
// -------------------- Blog --------------------
|
|
493
|
+
/**
|
|
494
|
+
* Read and manage blog posts.
|
|
495
|
+
*
|
|
496
|
+
* ```typescript
|
|
497
|
+
* // Storefront / vibe-coded: list published posts
|
|
498
|
+
* const { data: posts } = await brainerce.blog.getPosts({ category: 'news' });
|
|
499
|
+
*
|
|
500
|
+
* // Fetch one by slug
|
|
501
|
+
* const post = await brainerce.blog.getPost('my-first-post');
|
|
502
|
+
*
|
|
503
|
+
* // Admin: create a draft
|
|
504
|
+
* const draft = await brainerce.blog.create({ title: 'Hello World' });
|
|
505
|
+
* ```
|
|
506
|
+
*/
|
|
507
|
+
this.blog = /* @__PURE__ */ (() => {
|
|
508
|
+
const publicBase = "/blog/posts";
|
|
509
|
+
const adminBase = "/blog/posts";
|
|
510
|
+
const requireAdmin = (action) => {
|
|
511
|
+
if (this.isVibeCodedMode() || this.storeId && !this.apiKey) {
|
|
512
|
+
throw new BrainerceError(
|
|
513
|
+
`client.blog.${action}() requires admin mode (apiKey). Vibe-coded and storefront modes are read-only.`,
|
|
514
|
+
403
|
|
515
|
+
);
|
|
516
|
+
}
|
|
517
|
+
};
|
|
518
|
+
const onNotFound = (err) => {
|
|
519
|
+
if (err instanceof BrainerceError && err.statusCode === 404) return null;
|
|
520
|
+
throw err;
|
|
521
|
+
};
|
|
522
|
+
const buildQuery = (params) => Object.fromEntries(
|
|
523
|
+
Object.entries(params).filter(([, v]) => v != null).map(([k, v]) => [k, String(v)])
|
|
524
|
+
);
|
|
525
|
+
return {
|
|
526
|
+
/**
|
|
527
|
+
* List published posts. Works in all modes.
|
|
528
|
+
* Filters: `category`, `tag`, `page`, `limit`.
|
|
529
|
+
*/
|
|
530
|
+
getPosts: (params = {}) => {
|
|
531
|
+
const query = buildQuery(params);
|
|
532
|
+
if (this.isVibeCodedMode()) {
|
|
533
|
+
return this.vibeCodedRequest(
|
|
534
|
+
"GET",
|
|
535
|
+
publicBase,
|
|
536
|
+
void 0,
|
|
537
|
+
query
|
|
538
|
+
);
|
|
539
|
+
}
|
|
540
|
+
if (this.storeId && !this.apiKey) {
|
|
541
|
+
return this.storefrontRequest(
|
|
542
|
+
"GET",
|
|
543
|
+
publicBase,
|
|
544
|
+
void 0,
|
|
545
|
+
query
|
|
546
|
+
);
|
|
547
|
+
}
|
|
548
|
+
return this.adminRequest(
|
|
549
|
+
"GET",
|
|
550
|
+
adminBase,
|
|
551
|
+
void 0,
|
|
552
|
+
query
|
|
553
|
+
);
|
|
554
|
+
},
|
|
555
|
+
/**
|
|
556
|
+
* Fetch one published post by its slug. Returns `null` on 404.
|
|
557
|
+
* Works in all modes.
|
|
558
|
+
*/
|
|
559
|
+
getPost: (slug) => {
|
|
560
|
+
const path = `${publicBase}/${encodeURIComponent(slug)}`;
|
|
561
|
+
if (this.isVibeCodedMode()) {
|
|
562
|
+
return this.vibeCodedRequest("GET", path).catch(onNotFound);
|
|
563
|
+
}
|
|
564
|
+
if (this.storeId && !this.apiKey) {
|
|
565
|
+
return this.storefrontRequest("GET", path).catch(onNotFound);
|
|
566
|
+
}
|
|
567
|
+
return this.adminRequest("GET", path).catch(onNotFound);
|
|
568
|
+
},
|
|
569
|
+
/** Create a blog post in DRAFT status. Admin mode only. */
|
|
570
|
+
create: (input) => {
|
|
571
|
+
requireAdmin("create");
|
|
572
|
+
return this.adminRequest("POST", adminBase, input);
|
|
573
|
+
},
|
|
574
|
+
/** Update a blog post by ID. Admin mode only. */
|
|
575
|
+
update: (id, input) => {
|
|
576
|
+
requireAdmin("update");
|
|
577
|
+
return this.adminRequest(
|
|
578
|
+
"PATCH",
|
|
579
|
+
`${adminBase}/${encodeURIComponent(id)}`,
|
|
580
|
+
input
|
|
581
|
+
);
|
|
582
|
+
},
|
|
583
|
+
/** Transition status → PUBLISHED (sets publishedAt = now if unset). Admin mode only. */
|
|
584
|
+
publish: (id) => {
|
|
585
|
+
requireAdmin("publish");
|
|
586
|
+
return this.adminRequest(
|
|
587
|
+
"POST",
|
|
588
|
+
`${adminBase}/${encodeURIComponent(id)}/publish`
|
|
589
|
+
);
|
|
590
|
+
},
|
|
591
|
+
/** Transition status PUBLISHED → DRAFT. Admin mode only. */
|
|
592
|
+
unpublish: (id) => {
|
|
593
|
+
requireAdmin("unpublish");
|
|
594
|
+
return this.adminRequest(
|
|
595
|
+
"POST",
|
|
596
|
+
`${adminBase}/${encodeURIComponent(id)}/unpublish`
|
|
597
|
+
);
|
|
598
|
+
},
|
|
599
|
+
/** Hard-delete a blog post. Admin mode only. */
|
|
600
|
+
remove: async (id) => {
|
|
601
|
+
requireAdmin("remove");
|
|
602
|
+
await this.adminRequest("DELETE", `${adminBase}/${encodeURIComponent(id)}`);
|
|
603
|
+
}
|
|
604
|
+
};
|
|
605
|
+
})();
|
|
492
606
|
// -------------------- Local Cart (Client-Side for Guests) --------------------
|
|
493
607
|
// These methods store cart data in localStorage - NO API calls!
|
|
494
608
|
// Use for guest users in vibe-coded sites
|
|
@@ -8112,6 +8226,9 @@ var ALLOWED_PAYMENT_HOSTS = [
|
|
|
8112
8226
|
"grow.security",
|
|
8113
8227
|
// CreditGuard
|
|
8114
8228
|
"creditguard.co.il",
|
|
8229
|
+
// Takbull
|
|
8230
|
+
"takbull.co.il",
|
|
8231
|
+
"api.takbull.co.il",
|
|
8115
8232
|
// Brainerce-hosted payment embeds (backend payment-embed proxy at
|
|
8116
8233
|
// `/api/payment/embed/...` that fronts provider apps' embed shells —
|
|
8117
8234
|
// e.g. cardcom-payments OpenFields wrapper). The match also covers
|
package/dist/index.mjs
CHANGED
|
@@ -419,6 +419,120 @@ var BrainerceClient = class {
|
|
|
419
419
|
remove: removeById
|
|
420
420
|
};
|
|
421
421
|
})();
|
|
422
|
+
// -------------------- Blog --------------------
|
|
423
|
+
/**
|
|
424
|
+
* Read and manage blog posts.
|
|
425
|
+
*
|
|
426
|
+
* ```typescript
|
|
427
|
+
* // Storefront / vibe-coded: list published posts
|
|
428
|
+
* const { data: posts } = await brainerce.blog.getPosts({ category: 'news' });
|
|
429
|
+
*
|
|
430
|
+
* // Fetch one by slug
|
|
431
|
+
* const post = await brainerce.blog.getPost('my-first-post');
|
|
432
|
+
*
|
|
433
|
+
* // Admin: create a draft
|
|
434
|
+
* const draft = await brainerce.blog.create({ title: 'Hello World' });
|
|
435
|
+
* ```
|
|
436
|
+
*/
|
|
437
|
+
this.blog = /* @__PURE__ */ (() => {
|
|
438
|
+
const publicBase = "/blog/posts";
|
|
439
|
+
const adminBase = "/blog/posts";
|
|
440
|
+
const requireAdmin = (action) => {
|
|
441
|
+
if (this.isVibeCodedMode() || this.storeId && !this.apiKey) {
|
|
442
|
+
throw new BrainerceError(
|
|
443
|
+
`client.blog.${action}() requires admin mode (apiKey). Vibe-coded and storefront modes are read-only.`,
|
|
444
|
+
403
|
|
445
|
+
);
|
|
446
|
+
}
|
|
447
|
+
};
|
|
448
|
+
const onNotFound = (err) => {
|
|
449
|
+
if (err instanceof BrainerceError && err.statusCode === 404) return null;
|
|
450
|
+
throw err;
|
|
451
|
+
};
|
|
452
|
+
const buildQuery = (params) => Object.fromEntries(
|
|
453
|
+
Object.entries(params).filter(([, v]) => v != null).map(([k, v]) => [k, String(v)])
|
|
454
|
+
);
|
|
455
|
+
return {
|
|
456
|
+
/**
|
|
457
|
+
* List published posts. Works in all modes.
|
|
458
|
+
* Filters: `category`, `tag`, `page`, `limit`.
|
|
459
|
+
*/
|
|
460
|
+
getPosts: (params = {}) => {
|
|
461
|
+
const query = buildQuery(params);
|
|
462
|
+
if (this.isVibeCodedMode()) {
|
|
463
|
+
return this.vibeCodedRequest(
|
|
464
|
+
"GET",
|
|
465
|
+
publicBase,
|
|
466
|
+
void 0,
|
|
467
|
+
query
|
|
468
|
+
);
|
|
469
|
+
}
|
|
470
|
+
if (this.storeId && !this.apiKey) {
|
|
471
|
+
return this.storefrontRequest(
|
|
472
|
+
"GET",
|
|
473
|
+
publicBase,
|
|
474
|
+
void 0,
|
|
475
|
+
query
|
|
476
|
+
);
|
|
477
|
+
}
|
|
478
|
+
return this.adminRequest(
|
|
479
|
+
"GET",
|
|
480
|
+
adminBase,
|
|
481
|
+
void 0,
|
|
482
|
+
query
|
|
483
|
+
);
|
|
484
|
+
},
|
|
485
|
+
/**
|
|
486
|
+
* Fetch one published post by its slug. Returns `null` on 404.
|
|
487
|
+
* Works in all modes.
|
|
488
|
+
*/
|
|
489
|
+
getPost: (slug) => {
|
|
490
|
+
const path = `${publicBase}/${encodeURIComponent(slug)}`;
|
|
491
|
+
if (this.isVibeCodedMode()) {
|
|
492
|
+
return this.vibeCodedRequest("GET", path).catch(onNotFound);
|
|
493
|
+
}
|
|
494
|
+
if (this.storeId && !this.apiKey) {
|
|
495
|
+
return this.storefrontRequest("GET", path).catch(onNotFound);
|
|
496
|
+
}
|
|
497
|
+
return this.adminRequest("GET", path).catch(onNotFound);
|
|
498
|
+
},
|
|
499
|
+
/** Create a blog post in DRAFT status. Admin mode only. */
|
|
500
|
+
create: (input) => {
|
|
501
|
+
requireAdmin("create");
|
|
502
|
+
return this.adminRequest("POST", adminBase, input);
|
|
503
|
+
},
|
|
504
|
+
/** Update a blog post by ID. Admin mode only. */
|
|
505
|
+
update: (id, input) => {
|
|
506
|
+
requireAdmin("update");
|
|
507
|
+
return this.adminRequest(
|
|
508
|
+
"PATCH",
|
|
509
|
+
`${adminBase}/${encodeURIComponent(id)}`,
|
|
510
|
+
input
|
|
511
|
+
);
|
|
512
|
+
},
|
|
513
|
+
/** Transition status → PUBLISHED (sets publishedAt = now if unset). Admin mode only. */
|
|
514
|
+
publish: (id) => {
|
|
515
|
+
requireAdmin("publish");
|
|
516
|
+
return this.adminRequest(
|
|
517
|
+
"POST",
|
|
518
|
+
`${adminBase}/${encodeURIComponent(id)}/publish`
|
|
519
|
+
);
|
|
520
|
+
},
|
|
521
|
+
/** Transition status PUBLISHED → DRAFT. Admin mode only. */
|
|
522
|
+
unpublish: (id) => {
|
|
523
|
+
requireAdmin("unpublish");
|
|
524
|
+
return this.adminRequest(
|
|
525
|
+
"POST",
|
|
526
|
+
`${adminBase}/${encodeURIComponent(id)}/unpublish`
|
|
527
|
+
);
|
|
528
|
+
},
|
|
529
|
+
/** Hard-delete a blog post. Admin mode only. */
|
|
530
|
+
remove: async (id) => {
|
|
531
|
+
requireAdmin("remove");
|
|
532
|
+
await this.adminRequest("DELETE", `${adminBase}/${encodeURIComponent(id)}`);
|
|
533
|
+
}
|
|
534
|
+
};
|
|
535
|
+
})();
|
|
422
536
|
// -------------------- Local Cart (Client-Side for Guests) --------------------
|
|
423
537
|
// These methods store cart data in localStorage - NO API calls!
|
|
424
538
|
// Use for guest users in vibe-coded sites
|
|
@@ -8042,6 +8156,9 @@ var ALLOWED_PAYMENT_HOSTS = [
|
|
|
8042
8156
|
"grow.security",
|
|
8043
8157
|
// CreditGuard
|
|
8044
8158
|
"creditguard.co.il",
|
|
8159
|
+
// Takbull
|
|
8160
|
+
"takbull.co.il",
|
|
8161
|
+
"api.takbull.co.il",
|
|
8045
8162
|
// Brainerce-hosted payment embeds (backend payment-embed proxy at
|
|
8046
8163
|
// `/api/payment/embed/...` that fronts provider apps' embed shells —
|
|
8047
8164
|
// e.g. cardcom-payments OpenFields wrapper). The match also covers
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "brainerce",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.34.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",
|