@sayren/mcp 0.2.0 → 0.2.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sayren/mcp",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "sayren-mcp": "./dist/index.mjs"
@@ -12,8 +12,8 @@
12
12
  "dependencies": {
13
13
  "@modelcontextprotocol/sdk": "^1.22.0",
14
14
  "zod": "^4.6.5",
15
- "@sayren/storefront-sdk": "^0.8.0",
16
- "@sayren/store-sdk": "^0.8.0"
15
+ "@sayren/store-sdk": "^0.9.0",
16
+ "@sayren/storefront-sdk": "^0.9.0"
17
17
  },
18
18
  "devDependencies": {
19
19
  "@biomejs/biome": "^2.5.14",
@@ -7,8 +7,8 @@
7
7
  "zod": "^4.6.5"
8
8
  },
9
9
  "versions": {
10
- "@sayren/store-sdk": "0.8.0",
11
- "@sayren/storefront-sdk": "0.8.0",
10
+ "@sayren/store-sdk": "0.9.0",
11
+ "@sayren/storefront-sdk": "0.9.0",
12
12
  "@sayren/ui": "0.1.0"
13
13
  }
14
14
  }
@@ -1,6 +1,7 @@
1
1
  import type { ProductCard as ProductCardData } from "@sayren/storefront-sdk";
2
2
  import { Link } from "@tanstack/react-router";
3
3
  import { formatPrice } from "../lib/format";
4
+ import { ProductThumb } from "./product-thumb";
4
5
 
5
6
  /** 상품 카드 — 확장 지점: 찜 버튼·리뷰 별점 같은 요소는 여기에 붙인다 */
6
7
  export function ProductCard({ product }: { product: ProductCardData }) {
@@ -13,9 +14,8 @@ export function ProductCard({ product }: { product: ProductCardData }) {
13
14
  className="group flex flex-col gap-2"
14
15
  >
15
16
  <div className="relative aspect-square overflow-hidden rounded-lg bg-chip">
16
- <img
17
+ <ProductThumb
17
18
  src={product.thumbnailUrl}
18
- alt=""
19
19
  className="h-full w-full object-cover transition group-hover:scale-105"
20
20
  loading="lazy"
21
21
  />
@@ -0,0 +1,27 @@
1
+ interface ProductThumbProps {
2
+ /** 대표 이미지 주소. 등록된 이미지가 없으면 null이다 */
3
+ src: string | null;
4
+ alt?: string;
5
+ /** 크기·모서리 등 자리 클래스 — 이미지와 자리표시가 같은 박스를 쓴다 */
6
+ className: string;
7
+ loading?: "lazy" | "eager";
8
+ }
9
+
10
+ /**
11
+ * 상품 대표 이미지. `thumbnailUrl`이 null이면(이미지 없는 상품) 빈 자리를 그린다.
12
+ * 상품 이미지는 셀러가 콘솔에서 올리므로 아직 안 올린 상품이 섞일 수 있다.
13
+ */
14
+ export function ProductThumb({ src, alt = "", className, loading }: ProductThumbProps) {
15
+ if (!src) {
16
+ return (
17
+ <div
18
+ className={`${className} flex items-center justify-center bg-chip text-muted text-xs`}
19
+ role="img"
20
+ aria-label="이미지 없음"
21
+ >
22
+ 이미지 없음
23
+ </div>
24
+ );
25
+ }
26
+ return <img src={src} alt={alt} loading={loading} className={className} />;
27
+ }
@@ -2,6 +2,7 @@ import { createFileRoute, Link, useRouter } from "@tanstack/react-router";
2
2
  import { createServerFn } from "@tanstack/react-start";
3
3
  import { useState } from "react";
4
4
  import { z } from "zod";
5
+ import { ProductThumb } from "../components/product-thumb";
5
6
  import { SubmitButton } from "../components/submit-button";
6
7
  import { apiFor } from "../lib/api.server";
7
8
  import { readCartToken, writeCartToken } from "../lib/cart-session.server";
@@ -89,9 +90,8 @@ function CartPage() {
89
90
  <ul className="divide-y divide-line border-line border-y">
90
91
  {cart.items.map((item) => (
91
92
  <li key={item.cartItemId} className="flex gap-4 py-4">
92
- <img
93
+ <ProductThumb
93
94
  src={item.thumbnailUrl}
94
- alt=""
95
95
  className="size-20 rounded-md bg-chip object-cover"
96
96
  />
97
97
  <div className="flex flex-1 flex-col gap-1">
@@ -2,6 +2,7 @@ import { ApiError } from "@sayren/storefront-sdk";
2
2
  import { createFileRoute, Link, notFound, redirect } from "@tanstack/react-router";
3
3
  import { createServerFn } from "@tanstack/react-start";
4
4
  import { z } from "zod";
5
+ import { ProductThumb } from "../components/product-thumb";
5
6
  import { apiFor } from "../lib/api.server";
6
7
  import { formatDateTime, formatPrice } from "../lib/format";
7
8
  import { readToken } from "../lib/session.server";
@@ -43,9 +44,8 @@ function OrderDetail() {
43
44
  <ul className="divide-y divide-line border-line border-y">
44
45
  {order.items.map((item) => (
45
46
  <li key={item.orderItemId} className="flex items-center gap-4 py-4">
46
- <img
47
+ <ProductThumb
47
48
  src={item.thumbnailUrl}
48
- alt=""
49
49
  className="size-16 rounded-md bg-chip object-cover"
50
50
  />
51
51
  <span className="flex flex-1 flex-col gap-1 text-sm">
@@ -4,6 +4,7 @@ import { createServerFn } from "@tanstack/react-start";
4
4
  import { useState } from "react";
5
5
  import { z } from "zod";
6
6
  import { ProductDescription } from "../components/product-description";
7
+ import { ProductThumb } from "../components/product-thumb";
7
8
  import { SubmitButton } from "../components/submit-button";
8
9
  import { useTrack } from "../lib/analytics";
9
10
  import { apiFor } from "../lib/api.server";
@@ -74,7 +75,7 @@ function ProductDetail() {
74
75
  return (
75
76
  <div className="grid gap-8 md:grid-cols-2">
76
77
  <div className="space-y-3">
77
- <img src={product.thumbnailUrl} alt="" className="w-full rounded-lg bg-chip" />
78
+ <ProductThumb src={product.thumbnailUrl} className="w-full rounded-lg bg-chip" />
78
79
  {product.images.slice(0, 4).map((image) => (
79
80
  <img
80
81
  key={image}