@rovela-ai/sdk 0.21.0 → 0.23.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/dist/admin/api/email-sending.d.ts +24 -0
- package/dist/admin/api/email-sending.d.ts.map +1 -0
- package/dist/admin/api/email-sending.js +155 -0
- package/dist/admin/api/email-sending.js.map +1 -0
- package/dist/admin/api/index.d.ts +2 -0
- package/dist/admin/api/index.d.ts.map +1 -1
- package/dist/admin/api/index.js +4 -0
- package/dist/admin/api/index.js.map +1 -1
- package/dist/admin/api/integrations-brevo.d.ts +24 -0
- package/dist/admin/api/integrations-brevo.d.ts.map +1 -0
- package/dist/admin/api/integrations-brevo.js +286 -0
- package/dist/admin/api/integrations-brevo.js.map +1 -0
- package/dist/admin/api/integrations.d.ts +2 -0
- package/dist/admin/api/integrations.d.ts.map +1 -1
- package/dist/admin/api/integrations.js +1 -0
- package/dist/admin/api/integrations.js.map +1 -1
- package/dist/admin/api/products.d.ts.map +1 -1
- package/dist/admin/api/products.js +4 -0
- package/dist/admin/api/products.js.map +1 -1
- package/dist/admin/api/settings.d.ts.map +1 -1
- package/dist/admin/api/settings.js +4 -1
- package/dist/admin/api/settings.js.map +1 -1
- package/dist/admin/api/tax-zones.d.ts.map +1 -1
- package/dist/admin/api/tax-zones.js +7 -0
- package/dist/admin/api/tax-zones.js.map +1 -1
- package/dist/admin/components/EmailsManager.d.ts.map +1 -1
- package/dist/admin/components/EmailsManager.js +2 -1
- package/dist/admin/components/EmailsManager.js.map +1 -1
- package/dist/admin/components/IntegrationsManager.d.ts.map +1 -1
- package/dist/admin/components/IntegrationsManager.js +98 -2
- package/dist/admin/components/IntegrationsManager.js.map +1 -1
- package/dist/admin/components/OrderDetails.d.ts.map +1 -1
- package/dist/admin/components/OrderDetails.js +5 -1
- package/dist/admin/components/OrderDetails.js.map +1 -1
- package/dist/admin/components/ProductForm.d.ts.map +1 -1
- package/dist/admin/components/ProductForm.js +36 -1
- package/dist/admin/components/ProductForm.js.map +1 -1
- package/dist/admin/components/TaxSettings.d.ts.map +1 -1
- package/dist/admin/components/TaxSettings.js +16 -4
- package/dist/admin/components/TaxSettings.js.map +1 -1
- package/dist/admin/components/emails/EmailSendingPanel.d.ts +2 -0
- package/dist/admin/components/emails/EmailSendingPanel.d.ts.map +1 -0
- package/dist/admin/components/emails/EmailSendingPanel.js +131 -0
- package/dist/admin/components/emails/EmailSendingPanel.js.map +1 -0
- package/dist/admin/integrations/registry.d.ts +2 -0
- package/dist/admin/integrations/registry.d.ts.map +1 -1
- package/dist/admin/integrations/registry.js +41 -0
- package/dist/admin/integrations/registry.js.map +1 -1
- package/dist/admin/types.d.ts +15 -0
- package/dist/admin/types.d.ts.map +1 -1
- package/dist/checkout/api/manual.d.ts.map +1 -1
- package/dist/checkout/api/manual.js +7 -0
- package/dist/checkout/api/manual.js.map +1 -1
- package/dist/checkout/api/shipping.d.ts +0 -18
- package/dist/checkout/api/shipping.d.ts.map +1 -1
- package/dist/checkout/api/shipping.js +33 -3
- package/dist/checkout/api/shipping.js.map +1 -1
- package/dist/checkout/components/CheckoutFlow.d.ts.map +1 -1
- package/dist/checkout/components/CheckoutFlow.js +30 -13
- package/dist/checkout/components/CheckoutFlow.js.map +1 -1
- package/dist/checkout/components/OrderSummary.d.ts +1 -1
- package/dist/checkout/components/OrderSummary.d.ts.map +1 -1
- package/dist/checkout/components/OrderSummary.js +5 -2
- package/dist/checkout/components/OrderSummary.js.map +1 -1
- package/dist/checkout/server/create-checkout-session.d.ts.map +1 -1
- package/dist/checkout/server/create-checkout-session.js +38 -9
- package/dist/checkout/server/create-checkout-session.js.map +1 -1
- package/dist/checkout/server/handle-webhook.js +6 -0
- package/dist/checkout/server/handle-webhook.js.map +1 -1
- package/dist/checkout/server/order-service.d.ts.map +1 -1
- package/dist/checkout/server/order-service.js +21 -0
- package/dist/checkout/server/order-service.js.map +1 -1
- package/dist/checkout/server/pricing.d.ts +28 -1
- package/dist/checkout/server/pricing.d.ts.map +1 -1
- package/dist/checkout/server/pricing.js +84 -6
- package/dist/checkout/server/pricing.js.map +1 -1
- package/dist/checkout/types.d.ts +32 -0
- package/dist/checkout/types.d.ts.map +1 -1
- package/dist/core/db/queries.d.ts +114 -25
- package/dist/core/db/queries.d.ts.map +1 -1
- package/dist/core/db/queries.js +124 -2
- package/dist/core/db/queries.js.map +1 -1
- package/dist/core/db/schema.d.ts +213 -0
- package/dist/core/db/schema.d.ts.map +1 -1
- package/dist/core/db/schema.js +42 -0
- package/dist/core/db/schema.js.map +1 -1
- package/dist/emails/index.d.ts +2 -0
- package/dist/emails/index.d.ts.map +1 -1
- package/dist/emails/index.js +1 -0
- package/dist/emails/index.js.map +1 -1
- package/dist/emails/send/orders.d.ts +4 -0
- package/dist/emails/send/orders.d.ts.map +1 -1
- package/dist/emails/send/orders.js +1 -0
- package/dist/emails/send/orders.js.map +1 -1
- package/dist/emails/sender.d.ts.map +1 -1
- package/dist/emails/sender.js +30 -5
- package/dist/emails/sender.js.map +1 -1
- package/dist/emails/templates/order-confirmation.d.ts +9 -0
- package/dist/emails/templates/order-confirmation.d.ts.map +1 -1
- package/dist/emails/templates/order-confirmation.js +19 -8
- package/dist/emails/templates/order-confirmation.js.map +1 -1
- package/dist/emails/transport-smtp.d.ts +58 -0
- package/dist/emails/transport-smtp.d.ts.map +1 -0
- package/dist/emails/transport-smtp.js +97 -0
- package/dist/emails/transport-smtp.js.map +1 -0
- package/dist/emails/transport.d.ts +77 -0
- package/dist/emails/transport.d.ts.map +1 -0
- package/dist/emails/transport.js +154 -0
- package/dist/emails/transport.js.map +1 -0
- package/dist/emails/types.d.ts +5 -0
- package/dist/emails/types.d.ts.map +1 -1
- package/dist/products/api/products.d.ts.map +1 -1
- package/dist/products/api/products.js +18 -3
- package/dist/products/api/products.js.map +1 -1
- package/docs/changelog/epoch-09-catalog-tax.md +91 -0
- package/docs/changelog/epoch-10-email-transport.md +97 -0
- package/package.json +2 -1
- package/templates/store-template/.claude/skills/manage-products/SKILL.md +1 -1
- package/templates/store-template/app/account/orders/[id]/invoice/page.tsx +19 -4
- package/templates/store-template/app/api/admin/emails/sending/route.ts +9 -0
- package/templates/store-template/app/api/admin/integrations/brevo/backfill/route.ts +9 -0
- package/templates/store-template/app/api/admin/integrations/brevo/route.ts +9 -0
- package/templates/store-template/next.config.js +4 -1
- package/templates/store-template/package.json +2 -1
package/dist/emails/types.d.ts
CHANGED
|
@@ -151,6 +151,11 @@ export interface OrderConfirmationData {
|
|
|
151
151
|
shippingCost: string;
|
|
152
152
|
/** Formatted tax (e.g., "$8.00") */
|
|
153
153
|
tax: string;
|
|
154
|
+
/** Per-rate VAT ventilation (0.22.0), pre-formatted. Multi-rate orders only. */
|
|
155
|
+
taxBreakdown?: Array<{
|
|
156
|
+
rate: number;
|
|
157
|
+
amount: string;
|
|
158
|
+
}>;
|
|
154
159
|
/** Formatted total (e.g., "$112.00") */
|
|
155
160
|
total: string;
|
|
156
161
|
shippingAddress: EmailAddress;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/emails/types.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/emails/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"products.d.ts","sourceRoot":"","sources":["../../../src/products/api/products.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AACvD,OAAO,EACL,YAAY,
|
|
1
|
+
{"version":3,"file":"products.d.ts","sourceRoot":"","sources":["../../../src/products/api/products.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AACvD,OAAO,EACL,YAAY,EAKb,MAAM,uBAAuB,CAAA;AAQ9B,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC,CAAA;IAC9C,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,OAAO,CAAA;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;CACb;AAQD;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,GAAG,CACvB,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,YAAY,CAAC,mBAAmB,GAAG,gBAAgB,CAAC,CAAC,CAmH/D"}
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* ```
|
|
12
12
|
*/
|
|
13
13
|
import { NextResponse } from 'next/server';
|
|
14
|
-
import { findProducts, countProducts, findCategoryBySlug, } from '../../core/db/queries';
|
|
14
|
+
import { findProducts, countProducts, findCategoryBySlug, findCategoryDescendantIds, } from '../../core/db/queries';
|
|
15
15
|
import { getRequestLocale } from '../../core/server/request-locale';
|
|
16
16
|
import { localizeCatalogRows } from '../../core/i18n/catalog';
|
|
17
17
|
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
@@ -52,7 +52,7 @@ export async function GET(request) {
|
|
|
52
52
|
// matched nothing and the link showed the full catalog. An unknown slug
|
|
53
53
|
// returns an honest empty result instead.
|
|
54
54
|
const categoryParam = searchParams.get('category') || undefined;
|
|
55
|
-
let
|
|
55
|
+
let resolvedCategoryId = categoryParam;
|
|
56
56
|
if (categoryParam && !UUID_RE.test(categoryParam)) {
|
|
57
57
|
const category = await findCategoryBySlug(categoryParam);
|
|
58
58
|
if (!category) {
|
|
@@ -64,7 +64,22 @@ export async function GET(request) {
|
|
|
64
64
|
hasMore: false,
|
|
65
65
|
});
|
|
66
66
|
}
|
|
67
|
-
|
|
67
|
+
resolvedCategoryId = category.id;
|
|
68
|
+
}
|
|
69
|
+
// Tree-aware: a parent-category link includes its descendants' products
|
|
70
|
+
// (imported catalogs assign products to LEAF categories — PrestaShop-front
|
|
71
|
+
// behaviour). Leaf categories have no descendants → exact match, and a
|
|
72
|
+
// descendant-lookup failure degrades to exact match, never a 500.
|
|
73
|
+
let categoryId = resolvedCategoryId;
|
|
74
|
+
if (resolvedCategoryId) {
|
|
75
|
+
try {
|
|
76
|
+
const descendants = await findCategoryDescendantIds(resolvedCategoryId);
|
|
77
|
+
if (descendants.length > 0)
|
|
78
|
+
categoryId = [resolvedCategoryId, ...descendants];
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
/* exact match fallback */
|
|
82
|
+
}
|
|
68
83
|
}
|
|
69
84
|
const onSaleParam = searchParams.get('onSale');
|
|
70
85
|
const onSale = onSaleParam === '1' || onSaleParam === 'true' ? true : undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"products.js","sourceRoot":"","sources":["../../../src/products/api/products.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAe,YAAY,EAAE,MAAM,aAAa,CAAA;AACvD,OAAO,EACL,YAAY,EACZ,aAAa,EACb,kBAAkB,
|
|
1
|
+
{"version":3,"file":"products.js","sourceRoot":"","sources":["../../../src/products/api/products.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# E9 Catalog & tax — 0.22.0..0.22.0
|
|
2
|
+
|
|
3
|
+
## What landed
|
|
4
|
+
Two catalog-commerce behaviors every PrestaShop-migrated store needs: the
|
|
5
|
+
public category filter is now TREE-AWARE (a parent-category link includes its
|
|
6
|
+
descendant categories' products — imported catalogs assign products to leaf
|
|
7
|
+
categories), and TAX CLASSES bring per-product VAT rates (French 5.5%/20%
|
|
8
|
+
food split): products carry a `tax_class`, tax zones carry per-class rates,
|
|
9
|
+
and every money surface (quote, Stripe session, orders, emails, invoice,
|
|
10
|
+
admin) computes and renders the per-rate VAT ventilation ("dont TVA par
|
|
11
|
+
taux") French invoices legally require.
|
|
12
|
+
|
|
13
|
+
## SDK-internal (free)
|
|
14
|
+
- `findProducts`/`countProducts` accept `categoryId: string | string[]`
|
|
15
|
+
(IN-match). New `findCategoryDescendantIds(id)` (recursive CTE) and
|
|
16
|
+
`findTaxClassesByProductIds(ids)`.
|
|
17
|
+
- `resolveTax` accepts optional `lines` — per-line computation grouped by
|
|
18
|
+
rate, order discount allocated pro-rata (largest-remainder, sums exact),
|
|
19
|
+
shipping taxed at the zone's base rate. Returns `taxBreakdown` +
|
|
20
|
+
`taxClassRates`. Without `lines`, or on a zone with no `class_rates`, the
|
|
21
|
+
original lump formula runs — cent-identical to 0.21.x.
|
|
22
|
+
- `buildQuote` carries `taxBreakdown`/`taxClassRates` on the Quote; the
|
|
23
|
+
Stripe session divides each line by ITS OWN rate in tax-inclusive mode and
|
|
24
|
+
stamps `rovelaTaxBreakdown` metadata; both order writers persist
|
|
25
|
+
`orders.tax_breakdown`.
|
|
26
|
+
- Admin: TaxSettings zone editor gains per-class rate rows; ProductForm
|
|
27
|
+
gains a Tax class field (datalist fed from the zones' class names);
|
|
28
|
+
tax-zones API accepts `classRates`; products API accepts `taxClass`.
|
|
29
|
+
|
|
30
|
+
## Template contract
|
|
31
|
+
- `app/account/orders/[id]/invoice/page.tsx` — the totals block renders one
|
|
32
|
+
`TVA {rate}%` row per `order.taxBreakdown` entry when the order carries a
|
|
33
|
+
multi-rate ventilation, else the single flat tax row (stock shape: gated
|
|
34
|
+
branch on `order.taxBreakdown?.length > 1`). Stores with a customized
|
|
35
|
+
invoice keep their layout and add the same branch.
|
|
36
|
+
|
|
37
|
+
## Behavior contracts
|
|
38
|
+
- **Public `/api/products?category=` is tree-aware.** A parent category id or
|
|
39
|
+
slug now returns its own products PLUS every descendant category's. Stores
|
|
40
|
+
whose nav deliberately relied on parent links showing ONLY directly-assigned
|
|
41
|
+
products (rare; usually a bug they worked around) will see more products.
|
|
42
|
+
Admin product filters are UNCHANGED (exact match).
|
|
43
|
+
- **`OrderSummary` accepts `taxBreakdown`** and renders per-rate rows when
|
|
44
|
+
more than one rate is present; `CheckoutFlow` computes it from the estimate
|
|
45
|
+
response. Single-rate stores render byte-identically to 0.21.x.
|
|
46
|
+
- The pre-checkout shipping estimate (`/api/checkout/shipping`) accepts an
|
|
47
|
+
optional `productId` per item and returns `tax.breakdown`. Clients that
|
|
48
|
+
omit `productId` get the previous base-rate estimate (totals unchanged in
|
|
49
|
+
tax-inclusive stores).
|
|
50
|
+
|
|
51
|
+
## Custom-code hazards
|
|
52
|
+
- `grep -rn "resolveTax(" app lib components` — custom callers keep working
|
|
53
|
+
(the `lines` param is optional; omitted = old math). If a custom checkout
|
|
54
|
+
displays tax recomputed from `taxRate` alone, it cannot reproduce a
|
|
55
|
+
multi-rate cart: read `tax.breakdown`/`quote.taxBreakdown` when present
|
|
56
|
+
(see CheckoutFlow's per-group recompute for the reference implementation).
|
|
57
|
+
- `grep -rn "taxRate" app components` — any custom "TVA (20%)" label stays
|
|
58
|
+
correct for single-rate stores; multi-rate stores should render the
|
|
59
|
+
breakdown rows instead.
|
|
60
|
+
- `grep -rn "category=" app components lib` — store-authored nav links to
|
|
61
|
+
PARENT categories now include leaf products (this is almost always the
|
|
62
|
+
desired fix, not a regression).
|
|
63
|
+
|
|
64
|
+
## DB
|
|
65
|
+
- `products.tax_class varchar(50)` NULL — self-heals via
|
|
66
|
+
`ensureCatalogTranslationsSchema` (every catalog chokepoint).
|
|
67
|
+
- `tax_zones.class_rates jsonb NOT NULL DEFAULT '{}'` — self-heals via
|
|
68
|
+
`ensureVisibilityColumns`.
|
|
69
|
+
- `orders.tax_breakdown jsonb` NULL — self-heals via
|
|
70
|
+
`ensurePaymentMethodsSchema`.
|
|
71
|
+
- All three are additive with behavior-preserving defaults: no class rates
|
|
72
|
+
configured = 0.21.x math to the cent. Pre-applying is optional.
|
|
73
|
+
|
|
74
|
+
## New surfaces
|
|
75
|
+
- None. (TaxSettings/ProductForm gains are inside existing admin pages; no
|
|
76
|
+
new routes to mount.)
|
|
77
|
+
|
|
78
|
+
## Verify
|
|
79
|
+
1. `/products?category=<parent slug>` lists products assigned to child
|
|
80
|
+
categories; the admin Products page filtered to the same parent does NOT.
|
|
81
|
+
2. Settings → Tax: add a class rate (e.g. `tva-5-5` = 5.5) on the active
|
|
82
|
+
zone; assign the class to one product (Product form → Pricing → Tax
|
|
83
|
+
class).
|
|
84
|
+
3. Cart with one classed + one unclassed product → checkout review shows two
|
|
85
|
+
`TVA x%` rows summing to the receipt tax; totals unchanged
|
|
86
|
+
(tax-inclusive).
|
|
87
|
+
4. Place a test order → `orders.tax_breakdown` populated; invoice page and
|
|
88
|
+
order-confirmation email render the ventilation; admin order detail shows
|
|
89
|
+
per-rate rows.
|
|
90
|
+
5. A store that configures NO class rates: quote totals and every tax line
|
|
91
|
+
render exactly as before the update.
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# E10 Email sending & Brevo — 0.23.0..0.23.0
|
|
2
|
+
|
|
3
|
+
## What landed
|
|
4
|
+
Transactional-email delivery became merchant-configurable. Every store email
|
|
5
|
+
(order confirmations, account emails, custom emails) already funnels through
|
|
6
|
+
the SDK's one `sendEmail()` chokepoint; it now resolves a per-store
|
|
7
|
+
TRANSPORT: `'platform'` (default — the pre-0.23 Resend path, byte-identical
|
|
8
|
+
for the whole fleet), `'brevo'` (the store's connected Brevo account over
|
|
9
|
+
its HTTP API — same API key as the marketing integration, no SMTP key
|
|
10
|
+
needed), or `'smtp'` (the merchant's own server). The Brevo integration
|
|
11
|
+
also gained a live status echo and a one-click, resumable HISTORY IMPORT
|
|
12
|
+
that replaces per-store backfill scripts.
|
|
13
|
+
|
|
14
|
+
## SDK-internal (free via pin bump)
|
|
15
|
+
- `emails/transport.ts` — transport resolution + the two senders. **FAIL-SAFE
|
|
16
|
+
DELIVERY RULE**: a non-platform transport failure falls back to the
|
|
17
|
+
platform Resend path and logs loudly; a merchant's SMTP typo can never eat
|
|
18
|
+
an order confirmation. Misconfiguration surfaces at SAVE time instead
|
|
19
|
+
(real SMTP `verify()` handshake; Brevo verified-sender check).
|
|
20
|
+
- New `store_settings` columns (drizzle + `ensureStoreSettingsSchema` +
|
|
21
|
+
parent-branch ALTER at ship time): `email_transport`,
|
|
22
|
+
`email_from_address`, `email_from_name`, `smtp_host`, `smtp_port`,
|
|
23
|
+
`smtp_secure`, `smtp_user`, `smtp_password` (SERVER-ONLY secret — stripped
|
|
24
|
+
from the admin settings GET like `colissimo_password`; write-only, blank
|
|
25
|
+
keeps the stored value).
|
|
26
|
+
- `nodemailer` (pinned to the 7.x line — next-auth 4.x declares
|
|
27
|
+
`peerOptional nodemailer@^7` and npm refuses to hoist a different major)
|
|
28
|
+
became BOTH an SDK dependency and a TEMPLATE dependency (root-hoisted,
|
|
29
|
+
deterministic location). It loads through a BUNDLER-IGNORED dynamic
|
|
30
|
+
import (`webpackIgnore` + `turbopackIgnore`, isolated in
|
|
31
|
+
`emails/transport-smtp.ts`) — the emails graph is client-reachable, so a
|
|
32
|
+
static import breaks `next build`; the ignored import is native
|
|
33
|
+
server-runtime resolution, no path guessing.
|
|
34
|
+
- `EmailSendingPanel` (Sending card on /admin/emails) + `EmailsManager`
|
|
35
|
+
mounts it; the "Send a test" button exercises the REAL saved transport.
|
|
36
|
+
- Integrations registry entries gained `details` bullets (what each
|
|
37
|
+
integration actually does, rendered in the configure modal — all 10
|
|
38
|
+
entries authored).
|
|
39
|
+
- Brevo configure modal extras: live "Connected as x@y · plan" echo,
|
|
40
|
+
verified-sender status, the "send transactional emails through Brevo"
|
|
41
|
+
toggle (writes the same `email_transport` column as the Sending panel —
|
|
42
|
+
the two surfaces can never disagree), and the history import UI
|
|
43
|
+
(progress bar, resumable, include-orders switch defaulted OFF when
|
|
44
|
+
Brevo's eCommerce module already holds orders — the double-count guard).
|
|
45
|
+
|
|
46
|
+
## Template contract
|
|
47
|
+
- `app/api/admin/emails/sending/route.ts` (NEW) — re-export
|
|
48
|
+
`getEmailSending as GET, putEmailSending as PUT`. Without it the Sending
|
|
49
|
+
panel shows a load error and the Brevo toggle cannot save.
|
|
50
|
+
- `app/api/admin/integrations/brevo/route.ts` (NEW) — `getBrevoStatus as
|
|
51
|
+
GET`; `app/api/admin/integrations/brevo/backfill/route.ts` (NEW) —
|
|
52
|
+
`postBrevoBackfill as POST`. Without them the Brevo modal's extras show
|
|
53
|
+
an error state (credentials editing keeps working).
|
|
54
|
+
- **Component-dependency note (the E4 precedent)**: two per-store
|
|
55
|
+
requirements for the Custom-SMTP option — `package.json` gains
|
|
56
|
+
`"nodemailer": "7.0.13"` (MUST stay on 7.x: next-auth's peerOptional
|
|
57
|
+
range; a 8/9 pin makes npm nest it where the runtime can't resolve it)
|
|
58
|
+
and `next.config.js` gains
|
|
59
|
+
`outputFileTracingIncludes: ['./node_modules/nodemailer/**']` (an ignored
|
|
60
|
+
import is invisible to Vercel's tracer). A store updating the SDK WITHOUT
|
|
61
|
+
these loses only the Custom-SMTP option at runtime (platform + Brevo
|
|
62
|
+
transports are unaffected — Brevo is plain fetch), with a loud
|
|
63
|
+
`[Email] nodemailer not loadable` log.
|
|
64
|
+
|
|
65
|
+
## Behavior contracts
|
|
66
|
+
- `sendEmail()` behavior is UNCHANGED while `email_transport` is NULL /
|
|
67
|
+
'platform' — the entire existing fleet keeps its exact sending path.
|
|
68
|
+
- The Brevo history import is idempotent + resumable: contacts upsert by
|
|
69
|
+
email (`updateEnabled` — no duplicates, existing attributes/lists/consent
|
|
70
|
+
untouched, NO listIds ever sent), orders push with `historical: true`
|
|
71
|
+
(populates dashboards, NEVER fires an automation), chunked per request
|
|
72
|
+
(serverless-safe; the modal loops on the returned cursor).
|
|
73
|
+
- Per-store backfill scripts are RETIRED: the connect-brevo card + the
|
|
74
|
+
credentials contract now forbid writing one-off sync scripts into the
|
|
75
|
+
repo — history imports live in the admin.
|
|
76
|
+
|
|
77
|
+
## Custom-code hazards (audit greps for CC)
|
|
78
|
+
- Grep `scripts/` for hand-written Brevo/marketing backfill or sync scripts
|
|
79
|
+
(e.g. EasyElec's `scripts/brevo-backfill.mjs`) — superseded by
|
|
80
|
+
Integrations → Brevo → "Import history"; delete them.
|
|
81
|
+
- Grep for direct `getResend()` / `resend.emails.send` calls in store code —
|
|
82
|
+
they bypass the transport layer; route them through `sendEmail()` from
|
|
83
|
+
`@rovela-ai/sdk/emails`.
|
|
84
|
+
|
|
85
|
+
## MERCHANT-DATA HAZARD
|
|
86
|
+
None — no existing data changes meaning. The default transport is the
|
|
87
|
+
existing behavior; Brevo/SMTP are opt-in.
|
|
88
|
+
|
|
89
|
+
## Verify
|
|
90
|
+
- /admin/emails shows the Sending card; saving Custom SMTP with a wrong
|
|
91
|
+
host is REJECTED at save time with the handshake error.
|
|
92
|
+
- With Brevo connected: the integration modal shows "Connected as …", the
|
|
93
|
+
transactional toggle flips `email_transport`, and "Send a test" delivers
|
|
94
|
+
through Brevo (check the Brevo → Transactional log).
|
|
95
|
+
- The history import runs to 100% with a progress bar, is resumable after
|
|
96
|
+
an interruption, and fires zero automations (historical flag).
|
|
97
|
+
- A store with `email_transport` unset sends exactly as before.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rovela-ai/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.23.0",
|
|
4
4
|
"description": "Rovela SDK - Pre-built e-commerce components for AI-powered store generation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -320,6 +320,7 @@
|
|
|
320
320
|
"lucide-react": "0.555.0",
|
|
321
321
|
"nanoid": "5.1.6",
|
|
322
322
|
"next-auth": "4.24.13",
|
|
323
|
+
"nodemailer": "7.0.13",
|
|
323
324
|
"react-colorful": "^5.6.1",
|
|
324
325
|
"recharts": "3.7.0",
|
|
325
326
|
"resend": "6.9.1",
|
|
@@ -27,7 +27,7 @@ Usage: `nextjs_call` with `port="3000"` and `toolName="execute_sql"`
|
|
|
27
27
|
|
|
28
28
|
| Table | Key Columns |
|
|
29
29
|
|-------|-------------|
|
|
30
|
-
| `products` | id, name, slug, price, status (`draft`/`active`/`archived`), categoryId, hasVariants, images (JSONB string[]), videos (JSONB string[]), metafields (JSONB key/label/value/type), translations (JSONB per-locale name/description) |
|
|
30
|
+
| `products` | id, name, slug, price, status (`draft`/`active`/`archived`), categoryId, hasVariants, images (JSONB string[]), videos (JSONB string[]), metafields (JSONB key/label/value/type), translations (JSONB per-locale name/description), taxClass (0.22.0 — names a rate in tax_zones.class_rates; NULL = zone base rate) |
|
|
31
31
|
| `product_variants` | id, productId (CASCADE), sku, name, price, inventory, attributes (JSONB), image, video |
|
|
32
32
|
| `categories` | id, name, slug, parentId (self-ref), order, translations (JSONB) |
|
|
33
33
|
| `orders` | id, customerId, email, status, total, currency (ISO snapshot — display orders in THIS currency), refundAmount, returnReason, shippingAddress (JSONB) |
|
|
@@ -42,6 +42,8 @@ interface InvoiceOrder {
|
|
|
42
42
|
total: number
|
|
43
43
|
subtotal: number
|
|
44
44
|
tax: number
|
|
45
|
+
/** Per-rate VAT ventilation (0.22.0) — cents; null/absent = flat tax line. */
|
|
46
|
+
taxBreakdown?: Array<{ rate: number; baseCents: number; taxCents: number }> | null
|
|
45
47
|
shipping: number
|
|
46
48
|
discountAmount?: number | string
|
|
47
49
|
discountCode?: string | null
|
|
@@ -245,10 +247,23 @@ function InvoiceContent({ orderId }: { orderId: string }) {
|
|
|
245
247
|
<span>{t('common.shipping')}</span>
|
|
246
248
|
<span>{order.shipping > 0 ? formatPrice(order.shipping, orderCurrency) : t('common.free')}</span>
|
|
247
249
|
</div>
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
250
|
+
{order.taxBreakdown && order.taxBreakdown.length > 1 ? (
|
|
251
|
+
// Per-rate VAT ventilation (0.22.0) — the legally required French
|
|
252
|
+
// invoice breakdown ("dont TVA par taux").
|
|
253
|
+
order.taxBreakdown.map((entry) => (
|
|
254
|
+
<div key={entry.rate} className="flex justify-between text-muted-foreground">
|
|
255
|
+
<span>
|
|
256
|
+
{t('common.tax')} {entry.rate}%
|
|
257
|
+
</span>
|
|
258
|
+
<span>{formatPrice(entry.taxCents / 100, orderCurrency)}</span>
|
|
259
|
+
</div>
|
|
260
|
+
))
|
|
261
|
+
) : (
|
|
262
|
+
<div className="flex justify-between text-muted-foreground">
|
|
263
|
+
<span>{t('common.tax')}</span>
|
|
264
|
+
<span>{formatPrice(order.tax, orderCurrency)}</span>
|
|
265
|
+
</div>
|
|
266
|
+
)}
|
|
252
267
|
<div className="flex justify-between border-t pt-2 text-base font-semibold text-foreground">
|
|
253
268
|
<span>{t('common.total')}</span>
|
|
254
269
|
<span>{formatPrice(order.total, orderCurrency)}</span>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Email Sending Configuration Route
|
|
3
|
+
*
|
|
4
|
+
* GET /api/admin/emails/sending - Current transactional-email transport
|
|
5
|
+
* PUT /api/admin/emails/sending - Save it (SMTP handshake / Brevo verified-
|
|
6
|
+
* sender check run BEFORE persisting)
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export { getEmailSending as GET, putEmailSending as PUT } from '@rovela-ai/sdk/admin/api'
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Brevo History Import Route
|
|
3
|
+
*
|
|
4
|
+
* POST /api/admin/integrations/brevo/backfill - One chunk of the resumable
|
|
5
|
+
* history import (contacts upsert, then orders with historical:true so no
|
|
6
|
+
* automation fires). The integrations modal loops on the returned cursor.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export { postBrevoBackfill as POST } from '@rovela-ai/sdk/admin/api'
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Brevo Integration Status Route
|
|
3
|
+
*
|
|
4
|
+
* GET /api/admin/integrations/brevo - Live Brevo status for the
|
|
5
|
+
* integrations modal (account identity, sender verification, whether the
|
|
6
|
+
* eCommerce module already holds orders, current email transport).
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export { getBrevoStatus as GET } from '@rovela-ai/sdk/admin/api'
|
|
@@ -50,7 +50,10 @@ const nextConfig = {
|
|
|
50
50
|
// the SDK's core/config get the file, and every other function (checkout,
|
|
51
51
|
// webhooks, auth, admin emails) silently falls back to default styling.
|
|
52
52
|
outputFileTracingIncludes: {
|
|
53
|
-
|
|
53
|
+
// nodemailer is loaded via a bundler-invisible require (the emails graph
|
|
54
|
+
// is client-reachable, a static import breaks the build) so the tracer
|
|
55
|
+
// can't see it — force-include it or the SMTP transport 500s on Vercel.
|
|
56
|
+
'/**': ['./.rovela/blueprint.json', './node_modules/nodemailer/**'],
|
|
54
57
|
},
|
|
55
58
|
|
|
56
59
|
// Image domains for Unsplash, CDNs, and R2 storage
|
|
@@ -9,13 +9,14 @@
|
|
|
9
9
|
"lint": "eslint ."
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@rovela-ai/sdk": "0.
|
|
12
|
+
"@rovela-ai/sdk": "0.23.0",
|
|
13
13
|
"@tailwindcss/forms": "0.5.11",
|
|
14
14
|
"@tailwindcss/typography": "0.5.19",
|
|
15
15
|
"autoprefixer": "10.4.24",
|
|
16
16
|
"lucide-react": "0.555.0",
|
|
17
17
|
"next": "16.2.10",
|
|
18
18
|
"next-auth": "4.24.13",
|
|
19
|
+
"nodemailer": "7.0.13",
|
|
19
20
|
"postcss": "8.5.6",
|
|
20
21
|
"react": "19.2.4",
|
|
21
22
|
"react-dom": "19.2.4",
|