@ecomiq/storefront 0.1.2 → 1.0.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.
Files changed (56) hide show
  1. package/README.md +211 -59
  2. package/dist/chunk-PCTSWSTB.js +346 -0
  3. package/dist/chunk-PCTSWSTB.js.map +1 -0
  4. package/dist/chunk-PDK2VYWD.js +1598 -0
  5. package/dist/chunk-PDK2VYWD.js.map +1 -0
  6. package/dist/chunk-Q762YXCQ.js +175 -0
  7. package/dist/chunk-Q762YXCQ.js.map +1 -0
  8. package/dist/chunks/client.d.ts +8563 -0
  9. package/dist/chunks/client.js +2046 -0
  10. package/dist/chunks/client.js.map +1 -0
  11. package/dist/chunks/config.js +3 -0
  12. package/dist/chunks/config.js.map +1 -0
  13. package/dist/chunks/server-nextjs.d.ts +33 -0
  14. package/dist/chunks/server-nextjs.js +30 -0
  15. package/dist/chunks/server-nextjs.js.map +1 -0
  16. package/dist/chunks/server-tanstack.d.ts +22 -0
  17. package/dist/chunks/server-tanstack.js +30 -0
  18. package/dist/chunks/server-tanstack.js.map +1 -0
  19. package/dist/ecomiq-shell-ui-SWIFLQVM.js +8 -0
  20. package/dist/ecomiq-shell-ui-SWIFLQVM.js.map +1 -0
  21. package/dist/format-currency-oJD9jGYW.d.ts +6751 -0
  22. package/dist/index.d.ts +20 -30
  23. package/dist/index.js +11 -103
  24. package/dist/index.js.map +1 -1
  25. package/dist/index.server.d.ts +8 -0
  26. package/dist/index.server.js +7 -0
  27. package/dist/index.server.js.map +1 -0
  28. package/dist/nextjs/api.d.ts +10 -14
  29. package/dist/nextjs/api.js +8 -148
  30. package/dist/nextjs/api.js.map +1 -1
  31. package/dist/nextjs.d.ts +13 -3213
  32. package/dist/nextjs.js +11 -1793
  33. package/dist/nextjs.js.map +1 -1
  34. package/dist/nextjs.server.d.ts +1 -0
  35. package/dist/nextjs.server.js +1 -0
  36. package/dist/nextjs.server.js.map +1 -0
  37. package/dist/store-proxy-handler-CNzKlTFA.d.ts +10 -0
  38. package/dist/tanstack/api.d.ts +41 -0
  39. package/dist/tanstack/api.js +28 -0
  40. package/dist/tanstack/api.js.map +1 -0
  41. package/dist/tanstack.d.ts +13 -0
  42. package/dist/tanstack.js +11 -0
  43. package/dist/tanstack.js.map +1 -0
  44. package/dist/tanstack.server.d.ts +1 -0
  45. package/dist/tanstack.server.js +1 -0
  46. package/dist/tanstack.server.js.map +1 -0
  47. package/package.json +33 -13
  48. package/dist/collection-anMkdWa7.d.ts +0 -4333
  49. package/dist/core.d.ts +0 -3396
  50. package/dist/core.js +0 -1239
  51. package/dist/core.js.map +0 -1
  52. package/dist/find-storefront-cms-page-DNwLo1iV.d.ts +0 -178
  53. package/dist/react.d.ts +0 -964
  54. package/dist/react.js +0 -2670
  55. package/dist/react.js.map +0 -1
  56. /package/dist/{..d.ts → chunks/config.d.ts} +0 -0
package/README.md CHANGED
@@ -1,15 +1,15 @@
1
1
  # @ecomiq/storefront
2
2
 
3
- SDK **headless** para construir tu tienda con **Next.js** y **React** sobre la API de Ecomiq.
3
+ SDK **headless** para construir tu tienda con **Next.js** o **TanStack Start** y **React** sobre la API de Ecomiq.
4
4
 
5
- Incluye tipos, schemas Zod, cliente BFF (`/api/store`), hooks, `EcomiqProvider` y utilidades server. La interfaz de la tienda la implementas en tu proyecto.
5
+ Incluye tipos, schemas Zod, cliente BFF (`/api/store`), hooks, `EcomiqProvider` y bootstrap server por framework. **No incluye UI de tienda** (CMS, temas, checkout, etc.): la implementas en tu proyecto.
6
6
 
7
7
  ## Requisitos
8
8
 
9
9
  - Node.js 20+
10
- - Next.js 15+ (App Router)
11
10
  - React 19+
12
- - Tailwind CSS 4+ (opcional)
11
+ - **Next.js 15+** (App Router) *o* **TanStack Start** (`@tanstack/react-start`)
12
+ - Tailwind CSS 4+ (opcional; ver `/nextjs/css`)
13
13
 
14
14
  ## Instalación
15
15
 
@@ -19,6 +19,18 @@ npm install @ecomiq/storefront
19
19
  pnpm add @ecomiq/storefront
20
20
  ```
21
21
 
22
+ Instala también el peer de tu stack:
23
+
24
+ ```bash
25
+ # Next.js
26
+ pnpm add next react react-dom @tanstack/react-query better-auth
27
+
28
+ # TanStack Start
29
+ pnpm add @tanstack/react-start react react-dom @tanstack/react-query better-auth
30
+ ```
31
+
32
+ **Next.js** — en `next.config`:
33
+
22
34
  ```js
23
35
  /** @type {import('next').NextConfig} */
24
36
  const nextConfig = {
@@ -28,9 +40,9 @@ const nextConfig = {
28
40
  export default nextConfig;
29
41
  ```
30
42
 
31
- ## `ecomiq.config.js` (opcional)
43
+ ## `ecomiq.config.js`
32
44
 
33
- Puedes añadir en la **raíz de tu app** (junto a `next.config.js`) un archivo `ecomiq.config.js`, `ecomiq.config.cjs` o `ecomiq.config.mjs`:
45
+ En la **raíz de tu app** (`ecomiq.config.js`, `.cjs` o `.mjs`):
34
46
 
35
47
  ```js
36
48
  // @ts-check
@@ -43,20 +55,62 @@ const ecomiqConfig = {
43
55
  module.exports = ecomiqConfig;
44
56
  ```
45
57
 
46
- Si defines `slugStore`, `getPublicStore` usa ese slug como identificador de tienda y no lo infiere del header `Host`. Si no usas el archivo, la tienda se resuelve por el `Host` de la request (por ejemplo subdominio o dominio propio).
58
+ Si defines `slugStore`, `getPublicStore` usa ese slug (útil en localhost). Si no, deriva del header `Host`. Plantilla: [ecomiq.config.example.cjs](./ecomiq.config.example.cjs).
59
+
60
+ ## Puntos de entrada (npm)
61
+
62
+ | Import | Uso |
63
+ |--------|-----|
64
+ | `@ecomiq/storefront` | **Client:** `EcomiqProvider`, hooks (`useStoreProducts`, …). **Server** (`react-server`): config (`loadEcomiqConfig`, …) |
65
+ | `@ecomiq/storefront/nextjs` | **Server** (`react-server`): `getPublicStore`, cliente BFF server, auth helpers. **Client:** `EcomiqProvider`, hooks |
66
+ | `@ecomiq/storefront/nextjs/api` | Proxy `/api/store/*` (App Router) |
67
+ | `@ecomiq/storefront/nextjs/css` | Tailwind mínimo (opcional) |
68
+ | `@ecomiq/storefront/nextjs/postcss` | PostCSS de referencia |
69
+ | `@ecomiq/storefront/tanstack` | TanStack server + reexport client (misma API client que `/nextjs`) |
70
+ | `@ecomiq/storefront/tanstack/api` | Proxy `/api/store/*` (server routes) |
47
71
 
48
- Cuándo usarlo lo decides tú: en local, staging o producción. Plantilla: [ecomiq.config.example.cjs](./ecomiq.config.example.cjs).
72
+ Importa hooks desde `@ecomiq/storefront` o desde `@ecomiq/storefront/nextjs`. El build npm separa internamente server y client para App Router — **no necesitas** subpaths `/server` ni `/client`.
73
+
74
+ Los hooks (`useStoreProducts`, `useStoreCart`, …) tienen **una sola implementación** reexportada por ambos adapters; solo cambia el bootstrap server (`getPublicStore`, handler del proxy).
75
+
76
+ ### Peers
77
+
78
+ | Paquete | Cuándo |
79
+ |---------|--------|
80
+ | `react`, `react-dom` | Siempre |
81
+ | `next` | Solo si usas `/nextjs` |
82
+ | `@tanstack/react-start` | Solo si usas `/tanstack` |
83
+ | `@opennextjs/cloudflare` | Opcional (settings vía KV) |
49
84
 
50
85
  ## Arquitectura
51
86
 
52
87
  ```
53
- Navegador → /api/store/* (proxy en tu Next.js) → API Ecomiq
54
- ↑ X-Store-Id (tras getPublicStore)
88
+ ┌─────────────────────────────┐
89
+ │ @ecomiq/storefront │ ecomiq.config.js
90
+ └──────────────┬──────────────┘
91
+ │
92
+ ┌─────────────────────────┴─────────────────────────┐
93
+ ▼ ▼
94
+ /nextjs (+ /nextjs/api) /tanstack (+ /tanstack/api)
95
+ getPublicStore · toNextJsStoreApiHandler getPublicStore · createTanStackStoreApiHandler
96
+ │ │
97
+ └─────────────────────────┬─────────────────────────┘
98
+ ▼
99
+ Capa React compartida (hooks, EcomiqProvider, cliente BFF, auth)
100
+ │
101
+ ▼
102
+ core/server — fetchPublicStoreSettings · handleStoreProxyRequest
103
+ │
104
+ ▼
105
+ Navegador → /api/store/* (proxy en tu app) → API Ecomiq
106
+ ↑ contexto X-Store-Id (tras getPublicStore)
55
107
  ```
56
108
 
57
- El browser no llama al upstream directo; montas el proxy con `toNextJsStoreApiHandler`.
109
+ El browser **no** llama al upstream directo; montas el proxy con el adapter de tu framework.
58
110
 
59
- ## Inicio rápido
111
+ ---
112
+
113
+ ## Inicio rápido — Next.js
60
114
 
61
115
  ### 1. Proxy BFF
62
116
 
@@ -69,11 +123,32 @@ export const { GET, POST, PUT, PATCH, DELETE } = toNextJsStoreApiHandler({
69
123
  });
70
124
  ```
71
125
 
126
+ Los hooks y `EcomiqProvider` son **Client Components** (`"use client"`). En el layout (Server Component) solo importes funciones server; el provider va en un archivo client aparte.
127
+
72
128
  ### 2. Layout y tienda
73
129
 
74
130
  ```tsx
75
- // app/layout.tsx (Server Component)
76
- import { getPublicStore, EcomiqProvider } from "@ecomiq/storefront/nextjs";
131
+ // app/ecomiq-provider.tsx
132
+ "use client";
133
+
134
+ import { EcomiqProvider } from "@ecomiq/storefront";
135
+ import type { StorefrontSettings } from "@ecomiq/storefront/nextjs";
136
+
137
+ export function EcomiqRootProvider({
138
+ store,
139
+ children,
140
+ }: {
141
+ store: StorefrontSettings | null;
142
+ children: React.ReactNode;
143
+ }) {
144
+ return <EcomiqProvider store={store}>{children}</EcomiqProvider>;
145
+ }
146
+ ```
147
+
148
+ ```tsx
149
+ // app/layout.tsx — Server Component
150
+ import { getPublicStore } from "@ecomiq/storefront/nextjs";
151
+ import { EcomiqRootProvider } from "./ecomiq-provider";
77
152
 
78
153
  export default async function RootLayout({ children }: { children: React.ReactNode }) {
79
154
  const { data: store, error } = await getPublicStore();
@@ -81,21 +156,25 @@ export default async function RootLayout({ children }: { children: React.ReactNo
81
156
  // tu página de error / tienda no encontrada
82
157
  }
83
158
  return (
84
- <EcomiqProvider store={store}>
85
- {children}
86
- </EcomiqProvider>
159
+ <html lang="es">
160
+ <body>
161
+ <EcomiqRootProvider store={store}>{children}</EcomiqRootProvider>
162
+ </body>
163
+ </html>
87
164
  );
88
165
  }
89
166
  ```
90
167
 
91
- `EcomiqProvider` hidrata el estado de la tienda (`useStore`, `setClientStoreId`) y React Query. La autenticación es opcional (pasos 5 y 6).
168
+ `getPublicStore` corre en el servidor. `EcomiqProvider` hidrata `useStore`, configura React Query y el `storeId` del cliente BFF — debe vivir en un módulo con `"use client"`.
92
169
 
93
170
  ### 3. Catálogo con hooks
94
171
 
172
+ Puedes importar hooks desde el paquete raíz o desde `/nextjs`:
173
+
95
174
  ```tsx
96
175
  "use client";
97
176
 
98
- import { useStoreProducts } from "@ecomiq/storefront/nextjs";
177
+ import { useStoreProducts } from "@ecomiq/storefront";
99
178
 
100
179
  export function ProductList() {
101
180
  const { useStorefrontProductsList } = useStoreProducts();
@@ -123,23 +202,97 @@ export default async function CatalogPage() {
123
202
  }
124
203
  ```
125
204
 
126
- ### 5. Autenticación (Better Auth + SDK)
205
+ ---
206
+
207
+ ## Inicio rápido — TanStack Start
127
208
 
128
- Instala [Better Auth](https://www.better-auth.com/) y los plugins del SDK (OAuth password grant con credenciales Ecomiq).
209
+ ### 1. Proxy BFF
210
+
211
+ Ruta splat: `/api/store/*` → `routes/api/store/$.ts`
212
+
213
+ ```ts
214
+ // src/routes/api/store/$.ts
215
+ import { createFileRoute } from "@tanstack/react-router";
216
+ import { createTanStackStoreApiHandler } from "@ecomiq/storefront/tanstack/api";
217
+
218
+ const storeApi = createTanStackStoreApiHandler({
219
+ apiBaseUrl: process.env.STOREFRONT_API_URL,
220
+ });
221
+
222
+ export const Route = createFileRoute("/api/store/$")({
223
+ server: { handlers: storeApi },
224
+ });
225
+ ```
226
+
227
+ ### 2. Tienda en root route
228
+
229
+ ```tsx
230
+ // src/components/ecomiq-provider.tsx
231
+ "use client";
232
+
233
+ import { EcomiqProvider } from "@ecomiq/storefront";
234
+ import type { StorefrontSettings } from "@ecomiq/storefront/tanstack";
235
+
236
+ export function EcomiqRootProvider({
237
+ store,
238
+ children,
239
+ }: {
240
+ store: StorefrontSettings | null;
241
+ children: React.ReactNode;
242
+ }) {
243
+ return <EcomiqProvider store={store}>{children}</EcomiqProvider>;
244
+ }
245
+ ```
246
+
247
+ ```tsx
248
+ // src/routes/__root.tsx
249
+ import { createRootRoute, Outlet } from "@tanstack/react-router";
250
+ import { getPublicStore } from "@ecomiq/storefront/tanstack";
251
+ import { EcomiqRootProvider } from "../components/ecomiq-provider";
252
+
253
+ export const Route = createRootRoute({
254
+ loader: async () => getPublicStore(),
255
+ component: RootComponent,
256
+ });
257
+
258
+ function RootComponent() {
259
+ const { data: store } = Route.useLoaderData();
260
+ return (
261
+ <EcomiqRootProvider store={store}>
262
+ <Outlet />
263
+ </EcomiqRootProvider>
264
+ );
265
+ }
266
+ ```
267
+
268
+ ### 3. Hooks (Client Components)
269
+
270
+ ```tsx
271
+ "use client";
272
+
273
+ import { useStoreProducts, useStoreCart } from "@ecomiq/storefront";
274
+ ```
275
+
276
+ ---
277
+
278
+ ## Autenticación (Better Auth + SDK)
279
+
280
+ Instala [Better Auth](https://www.better-auth.com/).
129
281
 
130
282
  **Servidor:**
131
283
 
132
284
  ```ts
133
285
  // lib/auth.ts
134
286
  import { betterAuth } from "better-auth";
135
- import { ecomiqOAuthPassword } from "@ecomiq/storefront/react";
287
+ import { ecomiqOAuthPassword } from "@ecomiq/storefront/nextjs";
288
+ // TanStack: import { ecomiqOAuthPassword } from "@ecomiq/storefront/tanstack";
136
289
 
137
290
  export const auth = betterAuth({
138
291
  plugins: [ecomiqOAuthPassword()],
139
292
  });
140
293
  ```
141
294
 
142
- **Ruta API:**
295
+ **Ruta API (Next.js):**
143
296
 
144
297
  ```ts
145
298
  // app/api/auth/[...all]/route.ts
@@ -156,26 +309,22 @@ export const { GET, POST } = toNextJsHandler(auth);
156
309
  "use client";
157
310
 
158
311
  import { createAuthClient } from "better-auth/react";
159
- import { ecomiqOAuthPasswordClient } from "@ecomiq/storefront/react";
312
+ import { ecomiqOAuthPasswordClient } from "@ecomiq/storefront/nextjs";
160
313
 
161
314
  export const authClient = createAuthClient({
162
315
  plugins: [ecomiqOAuthPasswordClient()],
163
316
  });
164
317
  ```
165
318
 
166
- **Layout** — añade `authClient` al provider del paso 2:
319
+ **Layout** — pasa `authClient` al provider:
167
320
 
168
321
  ```tsx
169
- import { authClient } from "@/lib/auth-client";
170
-
171
322
  <EcomiqProvider store={store} authClient={authClient}>
172
323
  {children}
173
324
  </EcomiqProvider>
174
325
  ```
175
326
 
176
- ### 6. Login, registro y logout
177
-
178
- Con el paso 5 configurado:
327
+ ### Login, registro y logout
179
328
 
180
329
  ```tsx
181
330
  "use client";
@@ -184,8 +333,6 @@ import {
184
333
  useStore,
185
334
  useStorefrontAuthClient,
186
335
  useStorefrontSession,
187
- } from "@ecomiq/storefront/react";
188
- import {
189
336
  registerCustomer,
190
337
  signInWithEcomiqCredentials,
191
338
  } from "@ecomiq/storefront/nextjs";
@@ -216,54 +363,44 @@ export function AccountActions() {
216
363
  return (
217
364
  <div>
218
365
  <p>Hola, {user?.firstName ?? user?.email}</p>
219
- <button type="button" onClick={() => signOut()}>
220
- Cerrar sesión
221
- </button>
366
+ <button type="button" onClick={() => signOut()}>Cerrar sesión</button>
222
367
  </div>
223
368
  );
224
369
  }
225
370
 
226
- return (
227
- <div>
228
- {/* Tu UI: formularios que llaman handleLogin / handleRegister */}
229
- </div>
230
- );
371
+ return <div>{/* Tu UI */}</div>;
231
372
  }
232
373
  ```
233
374
 
234
- - **Login:** `signInWithEcomiqCredentials` (headers de tienda los resuelve el SDK).
235
- - **Registro:** `registerCustomer`, luego login con las mismas credenciales.
236
- - **Logout:** `signOut()` de `useStorefrontSession`.
375
+ En TanStack, cambia el import a `@ecomiq/storefront/tanstack`.
237
376
 
238
- ## Puntos de entrada (npm)
377
+ ---
239
378
 
240
- | Import | Uso |
241
- |--------|-----|
242
- | `@ecomiq/storefront` | `EcomiqConfig`, `loadEcomiqConfig` (tipado de `ecomiq.config.js`) |
243
- | `@ecomiq/storefront/core` | Tipos, Zod, utilidades |
244
- | `@ecomiq/storefront/react` | `EcomiqProvider`, hooks, sesión (`useStorefrontSession`), plugins Better Auth |
245
- | `@ecomiq/storefront/nextjs` | `getPublicStore`, cliente BFF, `registerCustomer`, `signInWithEcomiqCredentials`, hooks `useStore*` |
246
- | `@ecomiq/storefront/nextjs/api` | Proxy `/api/store/*` |
379
+ ## Qué incluye cada adapter
380
+
381
+ Desde `/nextjs` o `/tanstack` obtienes:
247
382
 
248
- El cliente BFF se importa desde **`/nextjs`** (no hay subpath `./client` en npm).
383
+ - **Server:** `getPublicStore`, `getHostname`, `fetchPublicStoreSettings` (agnóstico)
384
+ - **Provider:** `EcomiqProvider`, `useStore`, `usePublicStore`
385
+ - **Hooks BFF:** `useStoreProducts`, `useStoreCollections`, `useStorePages`, `useStoreCart`
386
+ - **Cliente:** `getStorefrontProducts`, `registerCustomer`, servicios de carrito/cuenta, etc.
387
+ - **Auth:** `ecomiqOAuthPassword`, `ecomiqOAuthPasswordClient`, `signInWithEcomiqCredentials`, `useStorefrontSession`
388
+ - **Tipos y Zod:** `StorefrontSettings`, `StorefrontProduct`, schemas, `formatCurrency`
389
+ - **Utilidades:** `findStorefrontCmsPageBySlug`, selector de variantes de producto
249
390
 
250
391
  ## Variables de entorno
251
392
 
252
393
  | Variable | Descripción |
253
394
  |----------|-------------|
254
395
  | `STOREFRONT_API_URL` | URL base de la API de tienda (proxy) |
255
- | `PUBLIC_STORE_SETTINGS_SOURCE` | `api` (default) o `kv` (despliegues con KV) |
256
-
257
- Tras `getPublicStore`, el SDK configura el contexto de tienda en el servidor para las llamadas al proxy.
396
+ | `PUBLIC_STORE_SETTINGS_SOURCE` | `api` (default) o `kv` (Cloudflare KV vía `@opennextjs/cloudflare`) |
258
397
 
259
398
  **Identificador de tienda:** `slugStore` en `ecomiq.config.*` si existe; si no, header `Host`.
260
399
 
261
- ## Publicación del paquete
262
-
263
- Mantenimiento del tarball npm: [PUBLISHING.md](./PUBLISHING.md).
264
-
265
400
  ## Dependencias recomendadas
266
401
 
402
+ **Next.js:**
403
+
267
404
  ```json
268
405
  {
269
406
  "dependencies": {
@@ -277,6 +414,21 @@ Mantenimiento del tarball npm: [PUBLISHING.md](./PUBLISHING.md).
277
414
  }
278
415
  ```
279
416
 
417
+ **TanStack Start:**
418
+
419
+ ```json
420
+ {
421
+ "dependencies": {
422
+ "@ecomiq/storefront": "^0.1.0",
423
+ "@tanstack/react-query": "^5.66.0",
424
+ "@tanstack/react-start": "^1.0.0",
425
+ "better-auth": "^1.6.0",
426
+ "react": "^19.0.0",
427
+ "react-dom": "^19.0.0"
428
+ }
429
+ }
430
+ ```
431
+
280
432
  ## Soporte
281
433
 
282
434
  Documentación y credenciales: [ecomiq.pe](https://ecomiq.pe) (o el portal de tu organización).