@aurora-studio/starter-core 0.1.2 → 0.1.4
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/components/AddToCartButton.d.ts +0 -1
- package/dist/components/AddToCartButton.js +1 -46
- package/dist/components/AddToCartFly.d.ts +0 -1
- package/dist/components/AddToCartFly.js +1 -33
- package/dist/components/AuthProvider.d.ts +0 -1
- package/dist/components/AuthProvider.js +1 -79
- package/dist/components/CartLink.d.ts +0 -1
- package/dist/components/CartLink.js +1 -30
- package/dist/components/CartProvider.d.ts +0 -1
- package/dist/components/CartProvider.js +1 -125
- package/dist/components/CatalogueEmptyState.d.ts +0 -1
- package/dist/components/CatalogueEmptyState.js +1 -12
- package/dist/components/CatalogueFilters.d.ts +0 -1
- package/dist/components/CatalogueFilters.js +1 -88
- package/dist/components/CheckoutButton.d.ts +0 -1
- package/dist/components/CheckoutButton.js +1 -70
- package/dist/components/ConditionalHolmesScript.d.ts +0 -1
- package/dist/components/ConditionalHolmesScript.js +1 -17
- package/dist/components/FloatingLabelInput.d.ts +0 -1
- package/dist/components/FloatingLabelInput.js +1 -13
- package/dist/components/HolmesHomeRefresher.d.ts +0 -1
- package/dist/components/HolmesHomeRefresher.js +1 -19
- package/dist/components/HolmesProductViewTracker.d.ts +0 -1
- package/dist/components/HolmesProductViewTracker.js +1 -39
- package/dist/components/HolmesSprinkleIcon.d.ts +0 -1
- package/dist/components/HolmesSprinkleIcon.js +1 -9
- package/dist/components/HolmesTidbits.d.ts +0 -1
- package/dist/components/HolmesTidbits.js +1 -33
- package/dist/components/ProductCardSkeleton.d.ts +0 -1
- package/dist/components/ProductCardSkeleton.js +1 -5
- package/dist/components/ProductDetailTabs.d.ts +0 -1
- package/dist/components/ProductDetailTabs.js +1 -29
- package/dist/components/ProductImage.d.ts +0 -1
- package/dist/components/ProductImage.js +1 -33
- package/dist/components/ProductImageGallery.d.ts +0 -1
- package/dist/components/ProductImageGallery.js +1 -25
- package/dist/components/SearchDropdown.d.ts +7 -2
- package/dist/components/SearchDropdown.js +1 -145
- package/dist/components/SmartCartPanel.d.ts +0 -1
- package/dist/components/SmartCartPanel.js +1 -19
- package/dist/components/SortDropdown.d.ts +0 -1
- package/dist/components/SortDropdown.js +1 -25
- package/dist/components/StoreConfigContext.d.ts +0 -1
- package/dist/components/StoreConfigContext.js +1 -26
- package/dist/components/StoreContext.d.ts +0 -1
- package/dist/components/StoreContext.js +1 -73
- package/dist/components/StoreContextBar.d.ts +0 -1
- package/dist/components/StoreContextBar.js +1 -12
- package/dist/index.d.ts +0 -1
- package/dist/index.js +1 -31
- package/dist/lib/aurora.d.ts +0 -1
- package/dist/lib/aurora.js +1 -235
- package/dist/lib/format-price.d.ts +0 -1
- package/dist/lib/format-price.js +1 -18
- package/dist/lib/holmes-events.d.ts +0 -1
- package/dist/lib/holmes-events.js +1 -73
- package/dist/lib/image-url.d.ts +0 -1
- package/dist/lib/image-url.js +1 -70
- package/dist/lib/utils.d.ts +0 -1
- package/dist/lib/utils.js +1 -9
- package/package.json +14 -9
- package/dist/components/AddToCartButton.d.ts.map +0 -1
- package/dist/components/AddToCartFly.d.ts.map +0 -1
- package/dist/components/AuthProvider.d.ts.map +0 -1
- package/dist/components/CartLink.d.ts.map +0 -1
- package/dist/components/CartProvider.d.ts.map +0 -1
- package/dist/components/CatalogueEmptyState.d.ts.map +0 -1
- package/dist/components/CatalogueFilters.d.ts.map +0 -1
- package/dist/components/CheckoutButton.d.ts.map +0 -1
- package/dist/components/ConditionalHolmesScript.d.ts.map +0 -1
- package/dist/components/FloatingLabelInput.d.ts.map +0 -1
- package/dist/components/HolmesHomeRefresher.d.ts.map +0 -1
- package/dist/components/HolmesProductViewTracker.d.ts.map +0 -1
- package/dist/components/HolmesSprinkleIcon.d.ts.map +0 -1
- package/dist/components/HolmesTidbits.d.ts.map +0 -1
- package/dist/components/ProductCardSkeleton.d.ts.map +0 -1
- package/dist/components/ProductDetailTabs.d.ts.map +0 -1
- package/dist/components/ProductImage.d.ts.map +0 -1
- package/dist/components/ProductImageGallery.d.ts.map +0 -1
- package/dist/components/SearchDropdown.d.ts.map +0 -1
- package/dist/components/SmartCartPanel.d.ts.map +0 -1
- package/dist/components/SortDropdown.d.ts.map +0 -1
- package/dist/components/StoreConfigContext.d.ts.map +0 -1
- package/dist/components/StoreContext.d.ts.map +0 -1
- package/dist/components/StoreContextBar.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/lib/aurora.d.ts.map +0 -1
- package/dist/lib/format-price.d.ts.map +0 -1
- package/dist/lib/holmes-events.d.ts.map +0 -1
- package/dist/lib/image-url.d.ts.map +0 -1
- package/dist/lib/utils.d.ts.map +0 -1
|
@@ -1,73 +1 @@
|
|
|
1
|
-
"
|
|
2
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
-
import { createContext, useContext, useCallback, useState, useEffect, } from "react";
|
|
4
|
-
const LOCATION_KEY = "aurora-location";
|
|
5
|
-
const STORE_KEY = "aurora-selected-store";
|
|
6
|
-
function loadLocation() {
|
|
7
|
-
if (typeof window === "undefined")
|
|
8
|
-
return null;
|
|
9
|
-
try {
|
|
10
|
-
const stored = localStorage.getItem(LOCATION_KEY);
|
|
11
|
-
return stored ? JSON.parse(stored) : null;
|
|
12
|
-
}
|
|
13
|
-
catch {
|
|
14
|
-
return null;
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
function saveLocation(loc) {
|
|
18
|
-
if (typeof window === "undefined")
|
|
19
|
-
return;
|
|
20
|
-
localStorage.setItem(LOCATION_KEY, JSON.stringify(loc));
|
|
21
|
-
}
|
|
22
|
-
function loadStore() {
|
|
23
|
-
if (typeof window === "undefined")
|
|
24
|
-
return null;
|
|
25
|
-
try {
|
|
26
|
-
const stored = localStorage.getItem(STORE_KEY);
|
|
27
|
-
return stored ? JSON.parse(stored) : null;
|
|
28
|
-
}
|
|
29
|
-
catch {
|
|
30
|
-
return null;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
function saveStore(store) {
|
|
34
|
-
if (typeof window === "undefined")
|
|
35
|
-
return;
|
|
36
|
-
if (store) {
|
|
37
|
-
localStorage.setItem(STORE_KEY, JSON.stringify(store));
|
|
38
|
-
}
|
|
39
|
-
else {
|
|
40
|
-
localStorage.removeItem(STORE_KEY);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
const StoreContext = createContext(null);
|
|
44
|
-
export function StoreProvider({ children }) {
|
|
45
|
-
const [location, setLocationState] = useState(null);
|
|
46
|
-
const [store, setStoreState] = useState(null);
|
|
47
|
-
const [mounted, setMounted] = useState(false);
|
|
48
|
-
useEffect(() => {
|
|
49
|
-
setLocationState(loadLocation());
|
|
50
|
-
setStoreState(loadStore());
|
|
51
|
-
setMounted(true);
|
|
52
|
-
}, []);
|
|
53
|
-
const setLocation = useCallback((loc) => {
|
|
54
|
-
setLocationState(loc);
|
|
55
|
-
saveLocation(loc);
|
|
56
|
-
}, []);
|
|
57
|
-
const setStore = useCallback((s) => {
|
|
58
|
-
setStoreState(s);
|
|
59
|
-
saveStore(s);
|
|
60
|
-
}, []);
|
|
61
|
-
return (_jsx(StoreContext.Provider, { value: {
|
|
62
|
-
location: mounted ? location : null,
|
|
63
|
-
setLocation,
|
|
64
|
-
store: mounted ? store : null,
|
|
65
|
-
setStore,
|
|
66
|
-
}, children: children }));
|
|
67
|
-
}
|
|
68
|
-
export function useStore() {
|
|
69
|
-
const ctx = useContext(StoreContext);
|
|
70
|
-
if (!ctx)
|
|
71
|
-
throw new Error("useStore must be used within StoreProvider");
|
|
72
|
-
return ctx;
|
|
73
|
-
}
|
|
1
|
+
import{jsx as t}from"react/jsx-runtime";import{createContext as e,useContext as r,useCallback as n,useState as o,useEffect as l}from"react";const u="aurora-location",i="aurora-selected-store",c=e(null);export function StoreProvider({children:e}){const[r,a]=o(null),[s,f]=o(null),[d,S]=o(!1);l(()=>{a(function(){if("undefined"==typeof window)return null;try{const t=localStorage.getItem(u);return t?JSON.parse(t):null}catch{return null}}()),f(function(){if("undefined"==typeof window)return null;try{const t=localStorage.getItem(i);return t?JSON.parse(t):null}catch{return null}}()),S(!0)},[]);const m=n(t=>{a(t),function(t){"undefined"!=typeof window&&localStorage.setItem(u,JSON.stringify(t))}(t)},[]),w=n(t=>{f(t),function(t){"undefined"!=typeof window&&(t?localStorage.setItem(i,JSON.stringify(t)):localStorage.removeItem(i))}(t)},[]);return t(c.Provider,{value:{location:d?r:null,setLocation:m,store:d?s:null,setStore:w},children:e})}export function useStore(){const t=r(c);if(!t)throw new Error("useStore must be used within StoreProvider");return t}
|
|
@@ -1,12 +1 @@
|
|
|
1
|
-
"
|
|
2
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import Link from "next/link";
|
|
4
|
-
import { Store, MapPin } from "lucide-react";
|
|
5
|
-
import { useStore } from "./StoreContext";
|
|
6
|
-
export function StoreContextBar() {
|
|
7
|
-
const { store } = useStore();
|
|
8
|
-
if (store) {
|
|
9
|
-
return (_jsx("div", { className: "border-b border-aurora-border bg-aurora-bg px-4 py-2.5", children: _jsxs("div", { className: "max-w-6xl mx-auto flex items-center justify-between gap-4", children: [_jsxs("div", { className: "flex items-center gap-2 text-sm text-aurora-muted", children: [_jsx(Store, { className: "w-4 h-4 shrink-0" }), _jsxs("span", { children: ["Shopping from: ", store.name] }), _jsx(Link, { href: "/stores", className: "text-aurora-primary hover:underline ml-1 font-medium", children: "View Store Details" })] }), _jsx(Link, { href: "/stores", className: "text-sm font-medium text-aurora-primary hover:underline", children: "Change Store" })] }) }));
|
|
10
|
-
}
|
|
11
|
-
return (_jsx("div", { className: "border-b border-aurora-border bg-aurora-primary/10 px-4 py-3", children: _jsxs("div", { className: "max-w-6xl mx-auto flex flex-wrap items-center justify-between gap-3", children: [_jsx("p", { className: "text-sm text-aurora-text font-medium", children: "Select a store to search products and see availability." }), _jsxs(Link, { href: "/location", className: "inline-flex items-center gap-2 px-4 py-2 rounded-lg bg-aurora-primary text-white font-semibold text-sm hover:bg-aurora-primary-dark transition-colors", children: [_jsx(MapPin, { className: "w-4 h-4 shrink-0" }), "Set location & choose store"] })] }) }));
|
|
12
|
-
}
|
|
1
|
+
import{jsx as e,jsxs as r}from"react/jsx-runtime";import a from"next/link";import{Store as t,MapPin as o}from"lucide-react";import{useStore as s}from"./StoreContext";export function StoreContextBar(){const{store:i}=s();return e("div",i?{className:"border-b border-aurora-border bg-aurora-bg px-4 py-2.5",children:r("div",{className:"max-w-6xl mx-auto flex items-center justify-between gap-4",children:[r("div",{className:"flex items-center gap-2 text-sm text-aurora-muted",children:[e(t,{className:"w-4 h-4 shrink-0"}),r("span",{children:["Shopping from: ",i.name]}),e(a,{href:"/stores",className:"text-aurora-primary hover:underline ml-1 font-medium",children:"View Store Details"})]}),e(a,{href:"/stores",className:"text-sm font-medium text-aurora-primary hover:underline",children:"Change Store"})]})}:{className:"border-b border-aurora-border bg-aurora-primary/10 px-4 py-3",children:r("div",{className:"max-w-6xl mx-auto flex flex-wrap items-center justify-between gap-3",children:[e("p",{className:"text-sm text-aurora-text font-medium",children:"Select a store to search products and see availability."}),r(a,{href:"/location",className:"inline-flex items-center gap-2 px-4 py-2 rounded-lg bg-aurora-primary text-white font-semibold text-sm hover:bg-aurora-primary-dark transition-colors",children:[e(o,{className:"w-4 h-4 shrink-0"}),"Set location & choose store"]})]})})}
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,31 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export * from "./lib/aurora";
|
|
3
|
-
export * from "./lib/format-price";
|
|
4
|
-
export * from "./lib/image-url";
|
|
5
|
-
export * from "./lib/utils";
|
|
6
|
-
export * from "./lib/holmes-events";
|
|
7
|
-
/** Components */
|
|
8
|
-
export * from "./components/AddToCartButton";
|
|
9
|
-
export * from "./components/AddToCartFly";
|
|
10
|
-
export * from "./components/AuthProvider";
|
|
11
|
-
export * from "./components/CartLink";
|
|
12
|
-
export * from "./components/CartProvider";
|
|
13
|
-
export * from "./components/CatalogueEmptyState";
|
|
14
|
-
export * from "./components/CatalogueFilters";
|
|
15
|
-
export * from "./components/CheckoutButton";
|
|
16
|
-
export * from "./components/ConditionalHolmesScript";
|
|
17
|
-
export * from "./components/FloatingLabelInput";
|
|
18
|
-
export * from "./components/HolmesHomeRefresher";
|
|
19
|
-
export * from "./components/HolmesProductViewTracker";
|
|
20
|
-
export * from "./components/HolmesSprinkleIcon";
|
|
21
|
-
export * from "./components/HolmesTidbits";
|
|
22
|
-
export * from "./components/ProductCardSkeleton";
|
|
23
|
-
export * from "./components/ProductDetailTabs";
|
|
24
|
-
export * from "./components/ProductImage";
|
|
25
|
-
export * from "./components/ProductImageGallery";
|
|
26
|
-
export * from "./components/SearchDropdown";
|
|
27
|
-
export * from "./components/SmartCartPanel";
|
|
28
|
-
export * from "./components/SortDropdown";
|
|
29
|
-
export * from "./components/StoreConfigContext";
|
|
30
|
-
export * from "./components/StoreContext";
|
|
31
|
-
export * from "./components/StoreContextBar";
|
|
1
|
+
export*from"./lib/aurora";export*from"./lib/format-price";export*from"./lib/image-url";export*from"./lib/utils";export*from"./lib/holmes-events";export*from"./components/AddToCartButton";export*from"./components/AddToCartFly";export*from"./components/AuthProvider";export*from"./components/CartLink";export*from"./components/CartProvider";export*from"./components/CatalogueEmptyState";export*from"./components/CatalogueFilters";export*from"./components/CheckoutButton";export*from"./components/ConditionalHolmesScript";export*from"./components/FloatingLabelInput";export*from"./components/HolmesHomeRefresher";export*from"./components/HolmesProductViewTracker";export*from"./components/HolmesSprinkleIcon";export*from"./components/HolmesTidbits";export*from"./components/ProductCardSkeleton";export*from"./components/ProductDetailTabs";export*from"./components/ProductImage";export*from"./components/ProductImageGallery";export*from"./components/SearchDropdown";export*from"./components/SmartCartPanel";export*from"./components/SortDropdown";export*from"./components/StoreConfigContext";export*from"./components/StoreContext";export*from"./components/StoreContextBar";
|
package/dist/lib/aurora.d.ts
CHANGED
package/dist/lib/aurora.js
CHANGED
|
@@ -1,235 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
const baseUrl = process.env.AURORA_API_URL ??
|
|
3
|
-
process.env.NEXT_PUBLIC_AURORA_API_URL ??
|
|
4
|
-
"";
|
|
5
|
-
const apiKey = process.env.AURORA_API_KEY ??
|
|
6
|
-
process.env.NEXT_PUBLIC_AURORA_API_KEY ??
|
|
7
|
-
"";
|
|
8
|
-
const tenantSlug = process.env.NEXT_PUBLIC_TENANT_SLUG ?? "";
|
|
9
|
-
/** Optional spec URL so the SDK can adjust from the tenant OpenAPI spec (default: baseUrl + /v1/openapi.json) */
|
|
10
|
-
const specUrl = baseUrl ? `${baseUrl.replace(/\/$/, "")}/v1/openapi.json` : undefined;
|
|
11
|
-
export function createAuroraClient() {
|
|
12
|
-
if (!baseUrl || baseUrl.startsWith("/")) {
|
|
13
|
-
throw new Error("Aurora API URL is not configured. Set AURORA_API_URL (or NEXT_PUBLIC_AURORA_API_URL) to your Aurora API root (e.g. https://api.youraurora.com).");
|
|
14
|
-
}
|
|
15
|
-
return new AuroraClient({ baseUrl, apiKey, specUrl });
|
|
16
|
-
}
|
|
17
|
-
export function getApiBase() {
|
|
18
|
-
return baseUrl.replace(/\/$/, "");
|
|
19
|
-
}
|
|
20
|
-
export function getTenantSlug() {
|
|
21
|
-
return tenantSlug;
|
|
22
|
-
}
|
|
23
|
-
/** Store config - safe for client: fetches via /api/store/config (keeps API key server-side). */
|
|
24
|
-
export async function getStoreConfig() {
|
|
25
|
-
if (typeof window !== "undefined") {
|
|
26
|
-
const res = await fetch("/api/store/config");
|
|
27
|
-
if (!res.ok)
|
|
28
|
-
return null;
|
|
29
|
-
return res.json();
|
|
30
|
-
}
|
|
31
|
-
const client = createAuroraClient();
|
|
32
|
-
return client.store.config();
|
|
33
|
-
}
|
|
34
|
-
/** Exclude offers from search - offers are checkout-only discounts, not products. */
|
|
35
|
-
function excludeOffersFromSearch(result) {
|
|
36
|
-
const hits = result.hits ?? [];
|
|
37
|
-
const filtered = hits.filter((h) => h.tableSlug !== "offers");
|
|
38
|
-
return { ...result, hits: filtered };
|
|
39
|
-
}
|
|
40
|
-
/** Meilisearch-powered product search. Uses API route from client (keeps API key server-side). */
|
|
41
|
-
export async function search(params) {
|
|
42
|
-
let result;
|
|
43
|
-
if (typeof window !== "undefined") {
|
|
44
|
-
const qs = new URLSearchParams();
|
|
45
|
-
if (params.q != null && params.q !== "")
|
|
46
|
-
qs.set("q", params.q);
|
|
47
|
-
if (params.limit != null)
|
|
48
|
-
qs.set("limit", String(params.limit));
|
|
49
|
-
if (params.offset != null)
|
|
50
|
-
qs.set("offset", String(params.offset));
|
|
51
|
-
if (params.vendorId)
|
|
52
|
-
qs.set("vendorId", params.vendorId);
|
|
53
|
-
if (params.category)
|
|
54
|
-
qs.set("category", params.category);
|
|
55
|
-
if (params.sort)
|
|
56
|
-
qs.set("sort", params.sort);
|
|
57
|
-
if (params.order)
|
|
58
|
-
qs.set("order", params.order);
|
|
59
|
-
if (params.excludeDietary?.length) {
|
|
60
|
-
qs.set("excludeDietary", params.excludeDietary.join(","));
|
|
61
|
-
}
|
|
62
|
-
const res = await fetch(`/api/search?${qs.toString()}`);
|
|
63
|
-
if (!res.ok) {
|
|
64
|
-
const err = (await res.json().catch(() => ({})));
|
|
65
|
-
throw new Error(err.error ?? "Search failed");
|
|
66
|
-
}
|
|
67
|
-
result = (await res.json());
|
|
68
|
-
}
|
|
69
|
-
else {
|
|
70
|
-
const client = createAuroraClient();
|
|
71
|
-
result = await client.site.search(params);
|
|
72
|
-
}
|
|
73
|
-
return excludeOffersFromSearch(result);
|
|
74
|
-
}
|
|
75
|
-
/** Fetch delivery slots for a location */
|
|
76
|
-
export async function getDeliverySlots(lat, lng) {
|
|
77
|
-
const client = createAuroraClient();
|
|
78
|
-
return client.store.deliverySlots(lat, lng);
|
|
79
|
-
}
|
|
80
|
-
/** List stores/vendors */
|
|
81
|
-
export async function getStores() {
|
|
82
|
-
const client = createAuroraClient();
|
|
83
|
-
return client.site.stores();
|
|
84
|
-
}
|
|
85
|
-
/** Create checkout session (Stripe or ACME) */
|
|
86
|
-
export async function createCheckoutSession(params) {
|
|
87
|
-
const client = createAuroraClient();
|
|
88
|
-
return client.store.checkout.sessions.create(params);
|
|
89
|
-
}
|
|
90
|
-
/** Fetch ACME checkout session */
|
|
91
|
-
export async function getAcmeSession(sessionId) {
|
|
92
|
-
const client = createAuroraClient();
|
|
93
|
-
return client.store.checkout.acme.get(sessionId);
|
|
94
|
-
}
|
|
95
|
-
/** Complete ACME checkout */
|
|
96
|
-
export async function completeAcmeCheckout(sessionId, shippingAddress) {
|
|
97
|
-
const client = createAuroraClient();
|
|
98
|
-
return client.store.checkout.acme.complete(sessionId, shippingAddress);
|
|
99
|
-
}
|
|
100
|
-
/** Holmes mission inference */
|
|
101
|
-
export async function holmesInfer(sessionId) {
|
|
102
|
-
const client = createAuroraClient();
|
|
103
|
-
return client.holmes.infer(sessionId);
|
|
104
|
-
}
|
|
105
|
-
/** Holmes insights: products for a recipe (paella, curry, pasta). Uses holmes_insights.recipe_ideas. */
|
|
106
|
-
export async function holmesRecipeProducts(recipe, limit = 12, opts) {
|
|
107
|
-
if (typeof window !== "undefined") {
|
|
108
|
-
const qs = new URLSearchParams({ recipe, limit: String(limit) });
|
|
109
|
-
if (opts?.excludeDietary?.length)
|
|
110
|
-
qs.set("excludeDietary", opts.excludeDietary.join(","));
|
|
111
|
-
const res = await fetch(`/api/holmes/recipe-products?${qs.toString()}`);
|
|
112
|
-
if (!res.ok) {
|
|
113
|
-
const err = (await res.json().catch(() => ({})));
|
|
114
|
-
throw new Error(err.error ?? "Recipe products failed");
|
|
115
|
-
}
|
|
116
|
-
return res.json();
|
|
117
|
-
}
|
|
118
|
-
const client = createAuroraClient();
|
|
119
|
-
return client.store.holmesRecipeProducts(recipe, limit, opts);
|
|
120
|
-
}
|
|
121
|
-
/** Holmes recent recipes from cache. Ordered by most recently updated. Optional timeOfDay filters by morning/afternoon/evening. excludeDietary filters out recipes whose ingredients match excluded types. */
|
|
122
|
-
export async function holmesRecentRecipes(limit = 8, timeOfDay, opts) {
|
|
123
|
-
if (typeof window !== "undefined") {
|
|
124
|
-
const qs = new URLSearchParams({ limit: String(limit) });
|
|
125
|
-
if (timeOfDay)
|
|
126
|
-
qs.set("time_of_day", timeOfDay);
|
|
127
|
-
if (opts?.excludeDietary?.length)
|
|
128
|
-
qs.set("excludeDietary", opts.excludeDietary.join(","));
|
|
129
|
-
const res = await fetch(`/api/holmes/recipes?${qs.toString()}`);
|
|
130
|
-
if (!res.ok)
|
|
131
|
-
return { recipes: [] };
|
|
132
|
-
return res.json();
|
|
133
|
-
}
|
|
134
|
-
const client = createAuroraClient();
|
|
135
|
-
return client.store.holmesRecentRecipes(limit, timeOfDay, opts);
|
|
136
|
-
}
|
|
137
|
-
/** Holmes cached recipe. Fetches via AI on cache miss. */
|
|
138
|
-
export async function holmesRecipe(slug) {
|
|
139
|
-
if (typeof window !== "undefined") {
|
|
140
|
-
const res = await fetch(`/api/holmes/recipe/${encodeURIComponent(slug)}`);
|
|
141
|
-
if (!res.ok)
|
|
142
|
-
return null;
|
|
143
|
-
return res.json();
|
|
144
|
-
}
|
|
145
|
-
const client = createAuroraClient();
|
|
146
|
-
return client.store.holmesRecipe(slug);
|
|
147
|
-
}
|
|
148
|
-
/** Holmes tidbits for entity (recipe, ingredient, product). */
|
|
149
|
-
export async function holmesTidbits(entity, entityType = "recipe") {
|
|
150
|
-
if (typeof window !== "undefined") {
|
|
151
|
-
const qs = new URLSearchParams({ entity, entity_type: entityType });
|
|
152
|
-
const res = await fetch(`/api/holmes/tidbits?${qs.toString()}`);
|
|
153
|
-
if (!res.ok)
|
|
154
|
-
return { tidbits: [] };
|
|
155
|
-
return res.json();
|
|
156
|
-
}
|
|
157
|
-
const client = createAuroraClient();
|
|
158
|
-
return client.store.holmesTidbits(entity, entityType);
|
|
159
|
-
}
|
|
160
|
-
/** Holmes insights: products that go well with a given product. Uses holmes_insights.goes_well_with. */
|
|
161
|
-
export async function holmesGoesWith(productId, limit = 8, opts) {
|
|
162
|
-
if (typeof window !== "undefined") {
|
|
163
|
-
const qs = new URLSearchParams({ product_id: productId, limit: String(limit) });
|
|
164
|
-
if (opts?.excludeDietary?.length)
|
|
165
|
-
qs.set("excludeDietary", opts.excludeDietary.join(","));
|
|
166
|
-
const res = await fetch(`/api/holmes/goes-with?${qs.toString()}`);
|
|
167
|
-
if (!res.ok) {
|
|
168
|
-
const err = (await res.json().catch(() => ({})));
|
|
169
|
-
throw new Error(err.error ?? "Goes-with failed");
|
|
170
|
-
}
|
|
171
|
-
return res.json();
|
|
172
|
-
}
|
|
173
|
-
const client = createAuroraClient();
|
|
174
|
-
return client.store.holmesGoesWith(productId, limit, opts);
|
|
175
|
-
}
|
|
176
|
-
/** Holmes bundle/recipe options for cart. Returns 1–3 combos when cart has 2+ items. */
|
|
177
|
-
export async function holmesCombosForCart(params) {
|
|
178
|
-
const qs = new URLSearchParams({ cart_ids: params.cartIds.join(",") });
|
|
179
|
-
if (params.cartNames?.length)
|
|
180
|
-
qs.set("cart_names", params.cartNames.join(","));
|
|
181
|
-
if (params.limit)
|
|
182
|
-
qs.set("limit", String(params.limit));
|
|
183
|
-
if (params.sid)
|
|
184
|
-
qs.set("sid", params.sid);
|
|
185
|
-
const res = await fetch(`/api/holmes/combos-for-cart?${qs.toString()}`);
|
|
186
|
-
if (!res.ok)
|
|
187
|
-
return { combos: [] };
|
|
188
|
-
return res.json();
|
|
189
|
-
}
|
|
190
|
-
/** Set selected combo for session (from recipe picker). */
|
|
191
|
-
export async function holmesSelectCombo(params) {
|
|
192
|
-
const res = await fetch("/api/holmes/select-combo", {
|
|
193
|
-
method: "POST",
|
|
194
|
-
headers: { "Content-Type": "application/json" },
|
|
195
|
-
body: JSON.stringify(params),
|
|
196
|
-
});
|
|
197
|
-
if (!res.ok)
|
|
198
|
-
throw new Error("Failed to set selected combo");
|
|
199
|
-
return res.json();
|
|
200
|
-
}
|
|
201
|
-
/** Holmes insights: similar products by type (what_it_is). For substitutions - same product type, not complementary. */
|
|
202
|
-
export async function holmesSimilarProducts(productId, limit = 8, productName, opts) {
|
|
203
|
-
if (typeof window !== "undefined") {
|
|
204
|
-
const qs = new URLSearchParams({ product_id: productId, limit: String(limit) });
|
|
205
|
-
if (productName?.trim())
|
|
206
|
-
qs.set("product_name", productName.trim());
|
|
207
|
-
if (opts?.excludeDietary?.length)
|
|
208
|
-
qs.set("excludeDietary", opts.excludeDietary.join(","));
|
|
209
|
-
const res = await fetch(`/api/holmes/similar?${qs.toString()}`);
|
|
210
|
-
if (!res.ok) {
|
|
211
|
-
const err = (await res.json().catch(() => ({})));
|
|
212
|
-
throw new Error(err.error ?? "Similar products failed");
|
|
213
|
-
}
|
|
214
|
-
return res.json();
|
|
215
|
-
}
|
|
216
|
-
const client = createAuroraClient();
|
|
217
|
-
return client.store.holmesSimilar(productId, limit, productName, opts);
|
|
218
|
-
}
|
|
219
|
-
/** Home personalization - sections for SSR fallback. sid optional (omit for default sections). excludeDietary filters products and sections by dietary preferences. */
|
|
220
|
-
export async function getHomePersonalization(sid, opts) {
|
|
221
|
-
try {
|
|
222
|
-
const client = createAuroraClient();
|
|
223
|
-
const result = await client.store.homePersonalization(sid ?? "", undefined, opts);
|
|
224
|
-
return result;
|
|
225
|
-
}
|
|
226
|
-
catch {
|
|
227
|
-
return null;
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
// Holmes offers & chat: available in SDK 0.2.7+ via client.holmes.offers(), client.holmes.chat.send(), client.holmes.chat.list()
|
|
231
|
-
/** Current user metadata and related data (e.g. addresses) when userId is provided. Uses GET /me from tenant spec. */
|
|
232
|
-
export async function getMe(userId) {
|
|
233
|
-
const client = createAuroraClient();
|
|
234
|
-
return client.me({ userId });
|
|
235
|
-
}
|
|
1
|
+
import{AuroraClient as e}from"@aurora-studio/sdk";const t=process.env.AURORA_API_URL??process.env.NEXT_PUBLIC_AURORA_API_URL??"",r=process.env.AURORA_API_KEY??process.env.NEXT_PUBLIC_AURORA_API_KEY??"",o=process.env.NEXT_PUBLIC_TENANT_SLUG??"",n=t?`${t.replace(/\/$/,"")}/v1/openapi.json`:void 0;export function createAuroraClient(){if(!t||t.startsWith("/"))throw new Error("Aurora API URL is not configured. Set AURORA_API_URL (or NEXT_PUBLIC_AURORA_API_URL) to your Aurora API root (e.g. https://api.youraurora.com).");return new e({baseUrl:t,apiKey:r,specUrl:n})}export function getApiBase(){return t.replace(/\/$/,"")}export function getTenantSlug(){return o}export async function getStoreConfig(){if("undefined"!=typeof window){const e=await fetch("/api/store/config");return e.ok?e.json():null}return createAuroraClient().store.config()}export async function search(e){let t;if("undefined"!=typeof window){const r=new URLSearchParams;null!=e.q&&""!==e.q&&r.set("q",e.q),null!=e.limit&&r.set("limit",String(e.limit)),null!=e.offset&&r.set("offset",String(e.offset)),e.vendorId&&r.set("vendorId",e.vendorId),e.category&&r.set("category",e.category),e.sort&&r.set("sort",e.sort),e.order&&r.set("order",e.order),e.excludeDietary?.length&&r.set("excludeDietary",e.excludeDietary.join(","));const o=await fetch(`/api/search?${r.toString()}`);if(!o.ok){const e=await o.json().catch(()=>({}));throw new Error(e.error??"Search failed")}t=await o.json()}else{const r=createAuroraClient();t=await r.site.search(e)}return function(e){const t=(e.hits??[]).filter(e=>"offers"!==e.tableSlug);return{...e,hits:t}}(t)}export async function getDeliverySlots(e,t){return createAuroraClient().store.deliverySlots(e,t)}export async function getStores(){return createAuroraClient().site.stores()}export async function createCheckoutSession(e){return createAuroraClient().store.checkout.sessions.create(e)}export async function getAcmeSession(e){return createAuroraClient().store.checkout.acme.get(e)}export async function completeAcmeCheckout(e,t){return createAuroraClient().store.checkout.acme.complete(e,t)}export async function holmesInfer(e){return createAuroraClient().holmes.infer(e)}export async function holmesRecipeProducts(e,t=12,r){if("undefined"!=typeof window){const o=new URLSearchParams({recipe:e,limit:String(t)});r?.excludeDietary?.length&&o.set("excludeDietary",r.excludeDietary.join(","));const n=await fetch(`/api/holmes/recipe-products?${o.toString()}`);if(!n.ok){const e=await n.json().catch(()=>({}));throw new Error(e.error??"Recipe products failed")}return n.json()}return createAuroraClient().store.holmesRecipeProducts(e,t,r)}export async function holmesRecentRecipes(e=8,t,r){if("undefined"!=typeof window){const o=new URLSearchParams({limit:String(e)});t&&o.set("time_of_day",t),r?.excludeDietary?.length&&o.set("excludeDietary",r.excludeDietary.join(","));const n=await fetch(`/api/holmes/recipes?${o.toString()}`);return n.ok?n.json():{recipes:[]}}return createAuroraClient().store.holmesRecentRecipes(e,t,r)}export async function holmesRecipe(e){if("undefined"!=typeof window){const t=await fetch(`/api/holmes/recipe/${encodeURIComponent(e)}`);return t.ok?t.json():null}return createAuroraClient().store.holmesRecipe(e)}export async function holmesTidbits(e,t="recipe"){if("undefined"!=typeof window){const r=new URLSearchParams({entity:e,entity_type:t}),o=await fetch(`/api/holmes/tidbits?${r.toString()}`);return o.ok?o.json():{tidbits:[]}}return createAuroraClient().store.holmesTidbits(e,t)}export async function holmesGoesWith(e,t=8,r){if("undefined"!=typeof window){const o=new URLSearchParams({product_id:e,limit:String(t)});r?.excludeDietary?.length&&o.set("excludeDietary",r.excludeDietary.join(","));const n=await fetch(`/api/holmes/goes-with?${o.toString()}`);if(!n.ok){const e=await n.json().catch(()=>({}));throw new Error(e.error??"Goes-with failed")}return n.json()}return createAuroraClient().store.holmesGoesWith(e,t,r)}export async function holmesCombosForCart(e){const t=new URLSearchParams({cart_ids:e.cartIds.join(",")});e.cartNames?.length&&t.set("cart_names",e.cartNames.join(",")),e.limit&&t.set("limit",String(e.limit)),e.sid&&t.set("sid",e.sid);const r=await fetch(`/api/holmes/combos-for-cart?${t.toString()}`);return r.ok?r.json():{combos:[]}}export async function holmesSelectCombo(e){const t=await fetch("/api/holmes/select-combo",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)});if(!t.ok)throw new Error("Failed to set selected combo");return t.json()}export async function holmesSimilarProducts(e,t=8,r,o){if("undefined"!=typeof window){const n=new URLSearchParams({product_id:e,limit:String(t)});r?.trim()&&n.set("product_name",r.trim()),o?.excludeDietary?.length&&n.set("excludeDietary",o.excludeDietary.join(","));const i=await fetch(`/api/holmes/similar?${n.toString()}`);if(!i.ok){const e=await i.json().catch(()=>({}));throw new Error(e.error??"Similar products failed")}return i.json()}return createAuroraClient().store.holmesSimilar(e,t,r,o)}export async function getHomePersonalization(e,t){try{const r=createAuroraClient();return await r.store.homePersonalization(e??"",void 0,t)}catch{return null}}export async function getMe(e){return createAuroraClient().me({userId:e})}
|
|
@@ -7,4 +7,3 @@ export declare function formatPrice(cents: number, currency?: string): string;
|
|
|
7
7
|
* Convert Aurora DB price (decimal major units, e.g. 2.00) to cents for display/cart.
|
|
8
8
|
*/
|
|
9
9
|
export declare function toCents(rawPrice: number | null | undefined): number | undefined;
|
|
10
|
-
//# sourceMappingURL=format-price.d.ts.map
|
package/dist/lib/format-price.js
CHANGED
|
@@ -1,18 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* Format price for display. Aurora stores prices as decimal major units (e.g. 2.00 = £2).
|
|
3
|
-
* This helper expects cents (integer) and formats for display.
|
|
4
|
-
*/
|
|
5
|
-
export function formatPrice(cents, currency = "GBP") {
|
|
6
|
-
return new Intl.NumberFormat("en-GB", {
|
|
7
|
-
style: "currency",
|
|
8
|
-
currency,
|
|
9
|
-
}).format(cents / 100);
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* Convert Aurora DB price (decimal major units, e.g. 2.00) to cents for display/cart.
|
|
13
|
-
*/
|
|
14
|
-
export function toCents(rawPrice) {
|
|
15
|
-
if (rawPrice == null || !Number.isFinite(rawPrice))
|
|
16
|
-
return undefined;
|
|
17
|
-
return Math.round(Number(rawPrice) * 100);
|
|
18
|
-
}
|
|
1
|
+
export function formatPrice(r,e="GBP"){return new Intl.NumberFormat("en-GB",{style:"currency",currency:e}).format(r/100)}export function toCents(r){if(null!=r&&Number.isFinite(r))return Math.round(100*Number(r))}
|
|
@@ -1,73 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* Holmes event bridge - push storefront signals to the Holmes script.
|
|
3
|
-
* Works for any storefront: call directly or dispatch DOM events.
|
|
4
|
-
* The Holmes script (loaded via layout) listens and sends data to Aurora.
|
|
5
|
-
*
|
|
6
|
-
* Integration: paste <script src=".../holmes/v1/script.js?site=X"></script>
|
|
7
|
-
* then call these helpers or dispatch the equivalent CustomEvents.
|
|
8
|
-
*/
|
|
9
|
-
export function holmesRecipeView(slug, title) {
|
|
10
|
-
if (typeof document === "undefined")
|
|
11
|
-
return;
|
|
12
|
-
const s = String(slug || "").trim();
|
|
13
|
-
const t = String(title || "").trim();
|
|
14
|
-
if (!s || !t)
|
|
15
|
-
return;
|
|
16
|
-
holmesMissionLockCombo();
|
|
17
|
-
if (window.holmes?.setRecipeViewed)
|
|
18
|
-
window.holmes.setRecipeViewed(s, t);
|
|
19
|
-
document.dispatchEvent(new CustomEvent("holmes:recipeView", { detail: { slug: s, title: t } }));
|
|
20
|
-
}
|
|
21
|
-
/** Dispatch event for Holmes to add a bundle to cart. CartProvider listens and calls addItem. */
|
|
22
|
-
export function holmesAddBundle(products, tableSlug) {
|
|
23
|
-
if (typeof document === "undefined")
|
|
24
|
-
return;
|
|
25
|
-
document.dispatchEvent(new CustomEvent("holmes:addBundle", { detail: { products, tableSlug } }));
|
|
26
|
-
}
|
|
27
|
-
const MEAL_SEARCH_LOCK_RE = /dinner|lunch|breakfast|brunch|supper|recipe|cook\b|meal\b|paella|curry|pasta|steak|roast|ingredient|grill|bbq|beef|lamb|pork|salmon|chicken|fish/i;
|
|
28
|
-
/** Lock recipe/combo mission on the server until reset (meal searches, mission pills). */
|
|
29
|
-
export function holmesMissionLockCombo() {
|
|
30
|
-
if (typeof document === "undefined")
|
|
31
|
-
return;
|
|
32
|
-
document.dispatchEvent(new CustomEvent("holmes:missionLock", { detail: { key: "combo_mission" } }));
|
|
33
|
-
}
|
|
34
|
-
/** Clear sticky recipe mission (e.g. mission bar reset). */
|
|
35
|
-
export function holmesMissionLockClear() {
|
|
36
|
-
if (typeof document === "undefined")
|
|
37
|
-
return;
|
|
38
|
-
document.dispatchEvent(new CustomEvent("holmes:missionLockClear"));
|
|
39
|
-
}
|
|
40
|
-
export function holmesSearch(query) {
|
|
41
|
-
if (typeof window === "undefined")
|
|
42
|
-
return;
|
|
43
|
-
const q = String(query || "").trim();
|
|
44
|
-
if (!q)
|
|
45
|
-
return;
|
|
46
|
-
if (MEAL_SEARCH_LOCK_RE.test(q))
|
|
47
|
-
holmesMissionLockCombo();
|
|
48
|
-
if (window.holmes)
|
|
49
|
-
window.holmes.setSearch(q);
|
|
50
|
-
document.dispatchEvent(new CustomEvent("holmes:search", { detail: { q } }));
|
|
51
|
-
}
|
|
52
|
-
export function holmesProductView(productIds) {
|
|
53
|
-
if (typeof window === "undefined")
|
|
54
|
-
return;
|
|
55
|
-
const ids = Array.isArray(productIds) ? productIds : [];
|
|
56
|
-
if (ids.length === 0)
|
|
57
|
-
return;
|
|
58
|
-
if (window.holmes)
|
|
59
|
-
window.holmes.setProductsViewed(ids);
|
|
60
|
-
document.dispatchEvent(new CustomEvent("holmes:productView", { detail: { productIds: ids } }));
|
|
61
|
-
}
|
|
62
|
-
export function holmesCartUpdate(count, items, bootstrap) {
|
|
63
|
-
if (typeof window === "undefined")
|
|
64
|
-
return;
|
|
65
|
-
if (window.holmes) {
|
|
66
|
-
window.holmes.setCartCount(count);
|
|
67
|
-
if (items)
|
|
68
|
-
window.holmes.setCartItems(items);
|
|
69
|
-
}
|
|
70
|
-
document.dispatchEvent(new CustomEvent("holmes:cartUpdate", {
|
|
71
|
-
detail: { count, items: items ?? [], bootstrap: bootstrap === true },
|
|
72
|
-
}));
|
|
73
|
-
}
|
|
1
|
+
export function holmesRecipeView(e,o){if("undefined"==typeof document)return;const t=String(e||"").trim(),n=String(o||"").trim();t&&n&&(holmesMissionLockCombo(),window.holmes?.setRecipeViewed&&window.holmes.setRecipeViewed(t,n),document.dispatchEvent(new CustomEvent("holmes:recipeView",{detail:{slug:t,title:n}})))}export function holmesAddBundle(e,o){"undefined"!=typeof document&&document.dispatchEvent(new CustomEvent("holmes:addBundle",{detail:{products:e,tableSlug:o}}))}const e=/dinner|lunch|breakfast|brunch|supper|recipe|cook\b|meal\b|paella|curry|pasta|steak|roast|ingredient|grill|bbq|beef|lamb|pork|salmon|chicken|fish/i;export function holmesMissionLockCombo(){"undefined"!=typeof document&&document.dispatchEvent(new CustomEvent("holmes:missionLock",{detail:{key:"combo_mission"}}))}export function holmesMissionLockClear(){"undefined"!=typeof document&&document.dispatchEvent(new CustomEvent("holmes:missionLockClear"))}export function holmesSearch(o){if("undefined"==typeof window)return;const t=String(o||"").trim();t&&(e.test(t)&&holmesMissionLockCombo(),window.holmes&&window.holmes.setSearch(t),document.dispatchEvent(new CustomEvent("holmes:search",{detail:{q:t}})))}export function holmesProductView(e){if("undefined"==typeof window)return;const o=Array.isArray(e)?e:[];0!==o.length&&(window.holmes&&window.holmes.setProductsViewed(o),document.dispatchEvent(new CustomEvent("holmes:productView",{detail:{productIds:o}})))}export function holmesCartUpdate(e,o,t){"undefined"!=typeof window&&(window.holmes&&(window.holmes.setCartCount(e),o&&window.holmes.setCartItems(o)),document.dispatchEvent(new CustomEvent("holmes:cartUpdate",{detail:{count:e,items:o??[],bootstrap:!0===t}})))}
|
package/dist/lib/image-url.d.ts
CHANGED
|
@@ -20,4 +20,3 @@ export declare function getImageUrlFromRecord(record: Record<string, unknown>):
|
|
|
20
20
|
* - Relative URLs get baseUrl prepended (storefront origin or imageBaseUrl from config).
|
|
21
21
|
*/
|
|
22
22
|
export declare function resolveProductImageUrl(url: string | null | undefined, baseUrl?: string | null): string | null;
|
|
23
|
-
//# sourceMappingURL=image-url.d.ts.map
|
package/dist/lib/image-url.js
CHANGED
|
@@ -1,70 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* Centralized product image URL resolution.
|
|
3
|
-
* Ensures relative URLs get correct base (storefront or CDN) so images load reliably.
|
|
4
|
-
* Supports Contentful CDN resize params to request appropriately-sized thumbnails.
|
|
5
|
-
*/
|
|
6
|
-
const IMAGE_FIELDS = ["image_url", "image", "thumbnail", "photo"];
|
|
7
|
-
/** Matches Contentful CDN URLs (images.ctfassets.net or images.eu.ctfassets.net), with or without protocol */
|
|
8
|
-
const CONTENTFUL_CDN_RE = /^(https?:)?\/\/images\.(eu\.)?ctfassets\.net\//i;
|
|
9
|
-
/**
|
|
10
|
-
* For Contentful CDN URLs, append resize params so the CDN returns an appropriately-sized
|
|
11
|
-
* image. Uses fit=pad to preserve aspect ratio and avoid cropping portrait/landscape images.
|
|
12
|
-
* Other URLs are returned unchanged.
|
|
13
|
-
*/
|
|
14
|
-
export function getThumbnailImageUrl(url, width = 400, height = 400) {
|
|
15
|
-
const raw = typeof url === "string" ? url.trim() : "";
|
|
16
|
-
if (!raw)
|
|
17
|
-
return null;
|
|
18
|
-
if (!CONTENTFUL_CDN_RE.test(raw))
|
|
19
|
-
return raw;
|
|
20
|
-
try {
|
|
21
|
-
const u = new URL(raw.startsWith("//") ? `https:${raw}` : raw);
|
|
22
|
-
const params = u.searchParams;
|
|
23
|
-
if (params.has("w") || params.has("h"))
|
|
24
|
-
return raw.startsWith("//") ? `https:${raw}` : raw;
|
|
25
|
-
params.set("w", String(Math.min(4000, width)));
|
|
26
|
-
params.set("h", String(Math.min(4000, height)));
|
|
27
|
-
params.set("fit", "pad");
|
|
28
|
-
params.set("fm", "webp");
|
|
29
|
-
return u.toString();
|
|
30
|
-
}
|
|
31
|
-
catch {
|
|
32
|
-
return raw;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Extract image URL from a product/record.
|
|
37
|
-
*/
|
|
38
|
-
export function getImageUrlFromRecord(record) {
|
|
39
|
-
const field = IMAGE_FIELDS.find((f) => record[f]);
|
|
40
|
-
return field ? String(record[field]).trim() || null : null;
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* Resolve product image URL for display.
|
|
44
|
-
* - Empty/invalid URLs return null.
|
|
45
|
-
* - Absolute URLs (http/https) returned as-is.
|
|
46
|
-
* - Relative URLs get baseUrl prepended (storefront origin or imageBaseUrl from config).
|
|
47
|
-
*/
|
|
48
|
-
export function resolveProductImageUrl(url, baseUrl) {
|
|
49
|
-
const raw = typeof url === "string" ? url.trim() : "";
|
|
50
|
-
if (!raw)
|
|
51
|
-
return null;
|
|
52
|
-
if (raw.startsWith("http://") || raw.startsWith("https://")) {
|
|
53
|
-
return raw;
|
|
54
|
-
}
|
|
55
|
-
if (raw.startsWith("//")) {
|
|
56
|
-
return `https:${raw}`;
|
|
57
|
-
}
|
|
58
|
-
const base = baseUrl ??
|
|
59
|
-
process.env.NEXT_PUBLIC_IMAGE_BASE_URL?.trim() ??
|
|
60
|
-
(typeof window !== "undefined"
|
|
61
|
-
? window.location?.origin
|
|
62
|
-
: null) ??
|
|
63
|
-
process.env.NEXT_PUBLIC_APP_URL?.trim() ??
|
|
64
|
-
"";
|
|
65
|
-
if (!base)
|
|
66
|
-
return raw.startsWith("/") ? raw : `/${raw}`;
|
|
67
|
-
const normalized = base.replace(/\/$/, "");
|
|
68
|
-
const path = raw.startsWith("/") ? raw : `/${raw}`;
|
|
69
|
-
return `${normalized}${path}`;
|
|
70
|
-
}
|
|
1
|
+
const t=["image_url","image","thumbnail","photo"],r=/^(https?:)?\/\/images\.(eu\.)?ctfassets\.net\//i;export function getThumbnailImageUrl(t,e=400,n=400){const s="string"==typeof t?t.trim():"";if(!s)return null;if(!r.test(s))return s;try{const t=new URL(s.startsWith("//")?`https:${s}`:s),r=t.searchParams;return r.has("w")||r.has("h")?s.startsWith("//")?`https:${s}`:s:(r.set("w",String(Math.min(4e3,e))),r.set("h",String(Math.min(4e3,n))),r.set("fit","pad"),r.set("fm","webp"),t.toString())}catch{return s}}export function getImageUrlFromRecord(r){const e=t.find(t=>r[t]);return e&&String(r[e]).trim()||null}export function resolveProductImageUrl(t,r){const e="string"==typeof t?t.trim():"";if(!e)return null;if(e.startsWith("http://")||e.startsWith("https://"))return e;if(e.startsWith("//"))return`https:${e}`;const n=r??process.env.NEXT_PUBLIC_IMAGE_BASE_URL?.trim()??("undefined"!=typeof window?window.location?.origin:null)??process.env.NEXT_PUBLIC_APP_URL?.trim()??"";return n?`${n.replace(/\/$/,"")}${e.startsWith("/")?e:`/${e}`}`:e.startsWith("/")?e:`/${e}`}
|
package/dist/lib/utils.d.ts
CHANGED
package/dist/lib/utils.js
CHANGED
|
@@ -1,9 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export function getTimeOfDay() {
|
|
3
|
-
const hour = new Date().getHours();
|
|
4
|
-
if (hour >= 5 && hour < 12)
|
|
5
|
-
return "morning";
|
|
6
|
-
if (hour >= 12 && hour < 17)
|
|
7
|
-
return "afternoon";
|
|
8
|
-
return "evening";
|
|
9
|
-
}
|
|
1
|
+
export function getTimeOfDay(){const n=(new Date).getHours();return n>=5&&n<12?"morning":n>=12&&n<17?"afternoon":"evening"}
|
package/package.json
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aurora-studio/starter-core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"scripts": {
|
|
5
|
-
"build": "tsc -p tsconfig.build.json",
|
|
6
|
-
"prepare": "tsc -p tsconfig.build.json",
|
|
7
|
-
"typecheck": "tsc --noEmit"
|
|
5
|
+
"build": "tsc -p tsconfig.build.json && node scripts/minify-dist.mjs",
|
|
6
|
+
"prepare": "tsc -p tsconfig.build.json && node scripts/minify-dist.mjs",
|
|
7
|
+
"typecheck": "tsc --noEmit",
|
|
8
|
+
"lint": "eslint src --max-warnings 0"
|
|
8
9
|
},
|
|
9
10
|
"description": "Shared Aurora storefront primitives (SDK helpers, Holmes bridge, commerce UI) for Hippo templates.",
|
|
10
11
|
"license": "MIT",
|
|
@@ -30,22 +31,26 @@
|
|
|
30
31
|
"access": "public"
|
|
31
32
|
},
|
|
32
33
|
"peerDependencies": {
|
|
33
|
-
"@aurora-studio/sdk": "^0.2.
|
|
34
|
+
"@aurora-studio/sdk": "^0.2.28",
|
|
35
|
+
"lucide-react": ">=0.400",
|
|
34
36
|
"next": ">=14",
|
|
35
37
|
"react": "^18 || ^19",
|
|
36
|
-
"react-dom": "^18 || ^19"
|
|
37
|
-
"lucide-react": ">=0.400"
|
|
38
|
+
"react-dom": "^18 || ^19"
|
|
38
39
|
},
|
|
39
40
|
"devDependencies": {
|
|
40
|
-
"@aurora-studio/sdk": "^0.2.
|
|
41
|
+
"@aurora-studio/sdk": "^0.2.28",
|
|
42
|
+
"@eslint/js": "^10.0.1",
|
|
41
43
|
"@types/node": "^22.0.0",
|
|
42
44
|
"@types/react": "^19.0.0",
|
|
43
45
|
"@types/react-dom": "^19.0.0",
|
|
46
|
+
"eslint": "^10.1.0",
|
|
44
47
|
"lucide-react": "^0.454.0",
|
|
45
48
|
"next": "15.0.7",
|
|
46
49
|
"react": "^19.0.0",
|
|
47
50
|
"react-dom": "^19.0.0",
|
|
48
|
-
"
|
|
51
|
+
"terser": "^5.46.1",
|
|
52
|
+
"typescript": "^5.3.3",
|
|
53
|
+
"typescript-eslint": "^8.57.1"
|
|
49
54
|
},
|
|
50
55
|
"packageManager": "pnpm@10.32.1+sha512.a706938f0e89ac1456b6563eab4edf1d1faf3368d1191fc5c59790e96dc918e4456ab2e67d613de1043d2e8c81f87303e6b40d4ffeca9df15ef1ad567348f2be",
|
|
51
56
|
"author": "Marcel du Preez - @Purple-Napkin",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"AddToCartButton.d.ts","sourceRoot":"","sources":["../../src/components/AddToCartButton.tsx"],"names":[],"mappings":"AAOA,UAAU,oBAAoB;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,sFAAsF;IACtF,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,eAAe,CAAC,EAC9B,QAAQ,EACR,SAAS,EACT,IAAI,EACJ,UAAU,EACV,YAAY,EACZ,IAAW,EACX,QAAQ,EACR,SAAS,GACV,EAAE,oBAAoB,2CA4FtB"}
|